Login Register Pro documentation

This documentation covers how to install, use and customize Login Register Pro in your website or application.

While this documentation is comprehensive, it actually only takes 5 minutes to get up-and-running with LoginRegisterPro. The only thing necessary is to install the module and place the following code snippet in a template file where you want its output to go:

<?= $modules->get('LoginRegisterPro')->execute() ?>

That's all there is to it to get up-and-running. But I'm aware that many developers that license this module will be doing so with the intention of using it as part of a larger project where there is broader purpose for front-end user accounts beyond just creating and maintaining them. My experience has also been that many ProcessWire developers like the benefits of a well defined system without sacrificing control and customization of output. For these reasons, LoginRegisterPro is designed to accomodate all of those needs, and this documentation goes in-depth into multiple topics for when and if you want it.

Please do not think this means you have to read everything here to install and use LoginRegisterPro. Quite the contrary, LoginRegisterPro is very simple to get setup and running, and this comprehensive documentation is here for when you need it, as is our dedicated support board.

Table of contents

Installation

Install

Install the module as with any other module, placing the included files in /site/modules/LoginRegisterPro/, then going to “Modules > Refresh” in your admin. Click “install” for the module (on the “Site” tab).

Configure

After install, you should see a configuration screen for this module. This screen will let you determine what features you want to use with it, and what fields you want to allow for user registration and profile editing, among numerous other settings. Most of the settings are self explanatory with inline descriptions. Review the settings, make any needed changes and save. At this stage you may want to work with the defaults to some extent, and then come back to refine them after up and running. Feel free to also review the Configuration section of this documentation for additional details when ready.

Integration

After installation and initial configuration, now let’s integrate LoginRegisterPro into your website or application.

1. Create a new template file and template

  • Identify a template file in /site/templates/ that outputs basic page content like body copy. This can be any template file, but for any of ProcessWire’s default profiles, this would be a template file named /site/templates/basic-page.php.

  • Whatever it is named, copy the file to /site/templates/login-register.php, though feel free to change the name of it if you’d prefer. This will be the template file that handles LoginRegisterPro’s output.

  • In your admin, go to Setup > Templates > Add New, select your new template file, then save. Add whatever fields you need (LoginRegisterPro does not require any).

  • Optional: While on the Template edit screen, I also recommend clicking to the “Family” tab and on the “Can this template be used for new pages?” selecting the “One” option. This ensures that only one Page can be created that uses this template file. Save.

  • Please do not use ProCache, Template Cache, or any other kind of output caching on the template file that you use for LoginRegisterPro output.

2. Add LoginRegisterPro output to new template file

  • Open the template file from step 1 in your text/code editor and locate the place where your “main” content goes, such as body copy. This will be the location where LoginRegisterPro displays all of its output.

  • If your template file strategy is to use direct output or Markup Regions then proceed to “A” below. If your template strategy is to populate variables for delayed output then proceed to “B” below. If you aren’t sure, then proceed to “A”, as this is the more common scenario.

A. Direct output or Markup Regions:

Place the following where your body copy would usually be output in the template file:

<?= $modules->get('LoginRegisterPro')->execute() ?>

B. Delayed output:

Place the following where your body copy would go in the template file, replacing the $content variable with whatever variable name is used to contain the site’s main content:

$content = $modules->get('LoginRegisterPro')->execute();

Whether you used A or B above, that single line is all that you need, and the module will do the rest. We recommend starting with this simple output strategy to see how everything works by default. We’ll cover more custom strategies later.

3. Create a Page that uses your new template

  • In your ProcessWire admin, create a new Page that uses the new template you created above. At least to start, I recommend creating the Page as a child of your homepage and giving it the title/name of login-register.

  • Now chances are you’ll want to rename and/or move this page elsewhere, but for the sake of writing instructions we just need a way to refer to this page for now, so we’ll refer to it as the /login-register/ page from now on, regardless of where you have placed it, or what you have named it.

  • You are now finished with the basic installation and can test things out!

4. Testing it out

  • While still logged-in, view the new /login-register/ page you created in step 3 above. It should present you with links for Profile and Logout. Click the Profile link to test that out. Chances are you’ll see a Profile form that is ready for some CSS styling! Now test out the Logout function.

  • Now view the page while logged-out (you may already be there). You should see a login form along with a link to register for a new account. Click to register for a new account. Again, the form you see here might need CSS styling before it’s ready to use, but if it’s all visible now, go ahead and test it out and register for a new account.

  • Once you have a feel for how everything works with the default setup, you are ready to customize it for your installation.

5. Next steps

If everything above worked out well, you've now got a front-end system where users can register, login and edit their profile. Chances are, you are now wondering one of these things:

  • What can I do with my logged-in users (other than edit profile or logout)?
    The answer is: anything you want! LoginRegisterPro provides you with an authenticated user, and then you decide what you want that authenticated user for. The next section “After login” gets you started with the logic and covers a few scenarios to kick things off.

  • The output needs styling or markup adjustments, how do I do that?
    Chances are that LoginRegisterPro’s output won't look perfect at first because it needs some CSS styling, classes or other markup adjustments to look the way you want it to in your site or application. If this is what you'd like to work on now, move to the Customization section further in this documentation.

  • No questions or other questions? If you aren't sure where to proceed next, I'd suggest reviewing both the “After login” and “Customization” sections that follow. If you have other questions, please also feel free to visit the LoginRegisterPro support board and post your question(s) there.

After login

After a user is logged in, you can choose to display a main homepage for the user with links of actions they can perform (Option 1), you can redirect somewhere else that you want them to go (Option 2), or you can do whatever else you want (Option 3). We’ll cover each of these scenarios below:

Option 1: Displaying a user homepage

After logging in, if you want the user to have a main (homepage) with a list of links/actions they can proceed with, this is the option you want. It is also the default behavior of LoginRegisterPro. Meaning, you don't have to do anything extra to implement it, just this (which you already have in your template file):

<?= $modules->get('LoginRegisterPro')->execute() ?>

By default, LoginRegisterPro displays just two action links to logged-in users, and 1-2 different links to logged-out users. The logged-in links include “Profile” to edit the user profile, and “Logout” to logout the user. The logged-out links include “Register” and optionally “Forgot password” (if you have the ProcessForgotPassword module installed). If you would like to add additional action links, you can do the following in your template file, before calling $loginRegister->execute():

<?php
$loginRegister = $modules->get('LoginRegisterPro');

if($user->isLoggedin()) {
  // add links for logged-in user (in addition to Profile and Logout)
  $loginRegister->addLink('/prod/', 'View products');
  $loginRegister->addLink('/prod/add/', 'Add new product');
  // if you prefer, you can also add links as markup:
  $loginRegister->addLink("<a href='/prod/review/'>Review product</a>");
} else {
  // add links for logged-out user (in additon to Register)
  $loginRegister->addLink('/help/', 'Need help?');
}

// links added above will only appear to logged-in users
echo $loginRegister->execute();

Perhaps you don't want to use a list of links auto-generated by LoginRegisterPro, but do want to render your own markup and content—see Option 3 further down, which does just that.

Option 2: Redirecting elsewhere

Once a user is logged in, if you want to redirect them somewhere else in your site, you can do the following:

<?php
$loginRegister = $modules->get('LoginRegisterPro');
// set URL to redirect to once we have an authenticated user:
$loginRegister->setRedirectUrl('/some/other/page/');
echo $loginRegister->execute();

The above will only redirect to /some/other/page/ when appropriate.

Option 3: Rendering your own markup and content

If you want to perform some other action, like rendering your own markup and content, below is how you'd do that. In our example, we are displaying the page’s “body” field only if the user is logged in and ready, otherwise we give control to LoginRegisterPro:

<?php
$loginRegister = $modules->get('LoginRegisterPro');
if($loginRegister->userReady) {
  // we have an authenticated user that’s not editing profile
  echo "<h1>Welcome $user->name</h1>";
  echo $page->body;
} else {
  // we have non-auth user OR user is editing profile
  echo $loginRegister->execute();
}

It’s also fine to both output your $page->body while also giving control to the module. When the user is “ready”, it will simply output its links (Profile and Login) and any pending notifications, and then return control to you:

<?php
$loginRegister = $modules->get('LoginRegisterPro');
if($loginRegister->userReady) echo $page->body;
echo $loginRegister->execute();

The above would output the page body followed by the module’s notifications and then links. Maybe you’d prefer to output the notifications, then your body and then the rest of the module’s output (links). Here’s how you’d do that:

<?php
$loginRegister = $modules->get('LoginRegisterPro');
if($loginRegister->userReady) {
  echo $loginRegister->renderNotices();
  echo $page->body;
}
echo $loginRegister->execute();

Site-wide usage

This module works with PW’s access control

The LoginRegisterPro module is only necessary to login, logout, register, or confirm the user, or to let the user edit their profile settings. Outside of those actions, the LoginRegisterPro module does not even need to load. This is because everything else you need to maintain a logged-in user session is already taken care of by ProcessWire’s role-based access control system (RBAC).

ProcessWire lets you configure which roles have access to which pages, by way of their template. When editing any template in the admin, you’ll see an “Access” tab that lets you define what roles are allowed to view pages using that template. So if you wanted to setup a template used for pages that could only be viewed by users that registered with this module, you would enable access control for that template and check the box for the “login-register” role and “view” permission.

Outside of template access control settings, ProcessWire’s API also provides two functions that you are likely to find useful in working with logged-in users: $user->isLoggedin(); and $user->hasRole('role'); both of which are covered in the following sections.

Identifying logged-in users

$user->isLoggedin();

This function returns true if the user is logged-in and false if not. This is useful in cases where you want something to appear for logged-in users and not for others. For example, maybe you want to display edit-profile and logout links in your site’s navigation when you’ve got a logged-in user, and login and register links when not logged-in.

if($user->isLoggedin()) {
  echo "<li><a href='/path/?profile=1'>Edit profile</a></li>";
  echo "<li><a href='/path/?logout=1'>Logout</a></li>";"
} else {
  echo "<li><a href='/path/?login=1'>Login</a></li>";
  echo "<li><a href='/path/?register=1'>Register</a></li>";
}

Note: there is also a $user->isGuest(); method, which is simply the opposite of the $user->isLoggedin(); method. Use whichever you prefer.

if($user->isGuest()) {
  // user is not logged-in
  echo "<a href='/path/?login=1'>Login</a>";
} else {
  // user is logged-in
  echo "<a href='/path/?profile=1'>Profile</a>“;
}

In the above examples, you would replace /path/ with the path to your Page that is using your login-register template. This is the most efficient way to do it. But if your site is in development and/or you anticipate this page might move, you can ask the LoginRegisterPro module for the URLs too:

$loginRegister = $modules->get('LoginRegisterPro');
if($user->isLoggedin()) {
  echo "<li><a href='$loginRegister->profileUrl'>Edit profile</a></li>";
  echo "<li><a href='$loginRegister->logoutUrl'>Logout</a></li>";"
} else {
  echo "<li><a href='$loginRegister->loginUrl'>Login</a></li>";
  echo "<li><a href='$loginRegister->registerUrl'>Register</a></li>";
}

Identifying user by role

$user->hasRole('login-register');

In many environments, you may be dealing with multiple roles that any given user can have. The $user->hasRole() method lets you identify what kind of user you are dealing with. For instance a $user->hasRole('login-register'); call would return true if the current $user is one that had registered with the LoginRegisterPro module, and false if they were some other kind of user (or a non-authenticated Guest user). Below is a contrived example that makes use of the hasRole() method:

if($user->isLoggedin()) {
  // user is logged in
  if($user->hasRole('login-register')) {
    // user registered with LoginRegisterPro
    echo "<p>Hello there, user that registered with us</p>";
  } else if($user->hasRole('superuser')) {
    // this is an admin/superuser
    echo "<p>Welcome superuser</p>";
  } else {
    // this is some other kind of logged-in user
    echo "<p>Hi there, you are logged-in</p>";
  }
} else {
  // this is a guest user, not logged-in
  echo "<p>Hello guest, you are not logged-in</p>";
}

Customization

This module provides a good starting point, but you may find you want to customize the output, whether that's with CSS, markup, or the fields that appear in the registration and/or profile forms. In this section we'll cover all of this. Depending on what you need to change, some types of customizations may require using hooks, so you may also want to review the Hooks section in this documentation as well.

Customizing styles (CSS)

This module comes with only basic styles to make things workable. You should feel free to custom style the forms and elements as you see fit.

Moving styles: LoginRegisterPro outputs the CSS <link> tags in the output it produces from the execute() method call. If you instead want to output its CSS link tags in your document <head> (where they would traditionally be) you can do the following in the code where you are outputting your document head. Please ONLY do this on pages where you will later be calling LoginRegisterPro’s execute() method. When used, renderStyles() must called and its return value output before LoginRegisterPro’s execute():

<head>
  ...
  <?= $modules->get('LoginRegisterPro')->renderStyles() ?>
  ...
</head>

When you later call the execute() method for output, it will no longer include the CSS <link> tags that it did before, since you’ve now output them in your document head.

Customizing scripts (JS)

jQuery required: This module uses some jQuery. If jQuery is not present, and renderScripts is not disabled, it automatically adds a script reference to ProcessWire’s jQueryCore module.

Moving scripts: If you want to output the module’s script tags in the document <head> rather than in its execute() method output, you can use the same strategy shown above for Styles (CSS) except you would call the renderScripts() method instead. Again, please do this only in template files where you intend to later call LoginRegisterPro’s execute() method. When used, renderScripts() must called and its return value output before LoginRegisterPro’s execute():

<head>
  ...
  <?= $modules->get('LoginRegisterPro')->renderScripts() ?>
  ...
</head>

Customizing markup and/or class attributes (HTML)

It is preferable to style LoginRegisterPro’s default markup when possible. However, if you are using a custom CSS framework that requires certain markup, classes or attributes, you may find it worthwhile to modify the default markup or classes to take advantage of what the framework offers.

Most markup output by LoginRegisterPro is customizable, and since most of what the module outputs is form-based, it comes largely from the ProcessWire core’s Inputfield modules. There are a lot of markup properties that you can customize and we'll demonstrate most here in various examples.

When modifying any markup properties, you'll want to do so before any other method calls to the LoginRegisterPro module. You can modify any of the named markup properties like this example below, where we are specifying the markup to use for error notifications:

<?php
// get the module
$loginRegister = $modules->get('LoginRegisterPro');

// set markup for the error notification
$loginRegister->setMarkup('error', "<div class='error'>{out}</div>");

If you want to modify the markup for multiple properties in one call you can use an array for the first argument and omit the 2nd argument. In this case below, we are setting the markup to use for both error and success notifications, together:

$loginRegister->setMarkup([
  'error' => "<p class='error'>{out}</p>",
  'success' => "<p class='success'>{out}</p>",
]);

Default markup settings

Below is the default markup settings used by the LoginRegisterPro module, which should help to see which properties you want to change:

$loginRegister->setMarkup([
  // General Inputfield markup
  'list' => "<div {attrs}>{out}</div>",
  'item' => "<div {attrs}>{out}</div>",
  'item_label' => "<label class='InputfieldHeader' for='{for}'>{out}</label>",
  'item_label_hidden' => "<label class='InputfieldHeader'><span>{out}</span></label>",
  'item_content' => "<div class='InputfieldContent {class}'>{description}{out}{error}{notes}</div>",
  'item_error' => "<div class='LoginRegisterError'><small>{out}</small></div>",
  'item_description' => "<p class='description'>{out}</p>",
  'item_notes' => "<p class='notes'><small>{out}</small></p>",
  'item_detail' => "<p class='detail'>{out}</p>",
  'success' => "<p class='LoginRegisterNotice LoginRegisterMessage'>{out}</p>",
  'error' => "<p class='LoginRegisterNotice LoginRegisterError'>{out}</p>",
  'warning' => "<p class='LoginRegisterNotice LoginRegisterWarning'>{out}</p>",
  'item_icon' => "",
  'item_toggle' => "",

  // Specific Inputfield markup
  'InputfieldFieldset' => array(
    'item' => "<fieldset {attrs}>{out}</fieldset>", // i.e. InputfieldFieldset.item
    'item_label' => "<legend>{out}</legend>",
    'item_label_hidden' => "<legend style='display:none'>{out}</legend>",
    'item_content' => "<div class='InputfieldContent'>{out}</div>",
    'item_description' => "<p class='description'>{out}</p>",
    'item_notes' => "<p class='notes'><small>{out}</small></p>",
  ),

  // LoginRegisterPro general markup
  'wrap_output' => "<div class='LoginRegisterPro'>{out}</div>",
  'links_list' => "<ul class='{class}'>{out}</ul>",
  'links_item' => "<li class='{class}'>{out}</li>",
  'a' => "<a href='{href}'>{out}</a>",
  'css_link' => "<link rel='stylesheet' type='text/css' href='{href}' />",
]);

Targeting settings and attributes of Inputfield by type

In addition to the above, you can also specify the name of any Inputfield type/class (like we've done with the InputfieldFieldset property above) and adjust any of the item_* properties as needed. You may use the following properties as well, which specify classes and attributes rather than markup:

  • class (string): class attribute for input element.
  • wrapClass (string): class attribute for wrapping (.Inputfield) element that surrounds header and content.
  • headerClass (string): class attribute for header (.InputfieldHeader) element.
  • contentClass (string): class attribute for content (.InputfieldContent) element that surrounds input element.
  • attr (array): Associative array of additional attributes to add to <input> element.
  • wrapAttr (array): Associative array of additional attributes to add to wrapping (.Inputfield) element.
  • set (array): Associative array of any other properties you want to set to Inputfield object; such as label, description, notes, required, requiredLabel, columnWidth, appendMarkup, prependMarkup.

For an example of how these are used, see the example in this section below where we are setting Uikit v3 framework class attributes for various Inputfield types. But below is a brief snippet from that example that sets the class attribute for the InputfieldSubmit input, which is a <button> element:

$loginRegister->setMarkup([
  'InputfieldSubmit' => [ 'class' => 'uk-button uk-button-primary' ]
]); 

In this example below we're adding a 'placeholder' attribute to all Email Inputfields:

$loginRegister->setMarkup([
  'InputfieldEmail' => [
    'attr' => [ 'placeholder' => 'you@company.com' ]
  ]
]); 

Targetting settings and attributes of Inputfield by name

If you want to get even more specific than targeting Inputfields by type, you can also target them by name attribute. Do this by specifying the markup key as a selector of name=val where "name" is literally the word "name" and "val" is the name attribute of the field you want to target (as it appears in the form). For instance, if you wanted to target the "email" field on the Register form, and the "name" and "pass" fields of the Login form, you could do this:

$loginRegister->setMarkup([
  'name=register_email' => [
    'class' => 'uk-form-large',
    'attr' => [ 'placeholder' => 'you@company.com' ]
  ],
  'name=login_name' => [ 'columnWidth' => 50 ],
  'name=login_pass' => [ 'columnWidth' => 50 ]
]); 

The above example adds a class and placeholder attribute to the "email" field on the Register form, and adds 50% columnWidth properties to the "name" and "pass" fields on the Login form, so that they display side-by-side rather than stacked on top of each other.

Example of using Uikit v3 markup

Below is a more real-life example where we modify the markup for several things to make it consistent with the output of the Uikit v3 framework:

$loginRegister->setMarkup([
  // error notification
  'error' =>
    "<div class='uk-alert-danger' uk-alert>" .
      "<a class='uk-alert-close' uk-close></a>" .
      "<p><span uk-icon='warning'></span> {out}</p>" .
    "</div>",

   // success or message notification
  'success' =>
    "<div class='uk-alert-success' uk-alert>" .
      "<a class='uk-alert-close' uk-close></a>" .
      "<p><span uk-icon='check'></span> {out}</p>" .
    "</div>",

   // inline error notification (appears below input)
  'item_error' =>
    "<div class='uk-text-danger uk-text-small uk-margin-small-top'>" .
      "<span uk-icon='warning'></span> {out}" .
    "</div>",

   // wrapper for list of links generated by module
  'links_list' =>
    "<ul class='uk-list uk-list-divider LoginRegisterLinks'>{out}</ul>",

  // The following adds custom classes to certain input types.
  'InputfieldText' => [ 'class' => 'uk-input' ],
  'InputfieldTextarea' => [ 'class' => 'uk-textarea' ],
  'InputfieldSelect' => [ 'class' => 'uk-select' ],
  'InputfieldRadios' => [ 'class' => 'uk-radio' ],
  'InputfieldCheckbox' => [ 'class' => 'uk-checkbox' ],
  'InputfieldCheckboxes' => [ 'class' => 'uk-checkbox' ],
  'InputfieldSubmit' => [ 'class' => 'uk-button uk-button-primary' ],

  // Login form: make name & pass fields side-by-side 50% width
  'name=login_name' => [ 'columnWidth' => 50 ],
  'name=login_pass' => [ 'columnWidth' => 50 ]
]);

Customizing confirmation emails

The confirmation email is customized in the interactive module configuration in your admin at Modules > Configure > LoginRegisterPro. Open the “Confirm” fieldset to reveal the customization options for email. Here you can control the email subject, from email, from name, HTML body, text body, and even what WireMail module is used to send confirmation emails. In the next section, there is also a recipe for using multi-language confirmation emails.

Recipes

This section will be expanded as questions arise about how to achieve specific output needs.

Logout and/or profile links elsewhere in your site

A common need is to display “logout” and edit “profile” links for logged in users. Here’s how you can do that with LoginRegisterPro:

if($user->isLoggedIn()) {
  $loginRegister = $modules->get('LoginRegisterPro');
  echo "<a href='$loginRegister->logoutUrl'>Log out</a> ";
  echo "<a href='$loginRegister->profileUrl'>Edit profile</a> ";
}

Of course, you could also make the links manually if you preferred. This is a little better route because you won't have to load the LoginRegisterPro module on pages where you don't need it. The URL to logout is simply the URL of the page you are using this module on, plus a “logout” or “profile” GET variable, like this:

<?php if($user->isLoggedIn(): ?>
  <a href='/path/to/page/?logout=1'>Log out</a>
  <a href='/path/to/page/?profile=1'>Edit profile</a>
<?php endif; ?>

In the above example, the /path/to/page/ is the URL to the page where you are calling $loginRegister->execute();

Displaying separate login and register forms at the same time

In most cases, we recommend letting LoginRegisterPro handle the decision of what should be output by just calling its execute() method as in the examples above. However, if you have a specific need to display separate login and registration forms in different parts of the page at the same time, here's a recipe that will do that.

Usually LoginRegisterPro decides what is appropriate to display based on the current request. However, you can suggest that it should do something else by passing it an argument of 'login' or 'register'.

If you need to display the login and registration forms together, such as the login form in the sidebar, and the registration form in the main content, you can do so like this (replacing <main> and <aside> with your own markup):

<main>
  <?php
  $loginRegister = $modules->get('LoginRegisterPro');
  if($user->isLoggedin()) {
    // logged-in user: let it auto-detect what to display
    echo $loginRegister->execute();
  } else {
    // user not logged-in: tell it to display registration form
    echo $loginRegister->execute('register');
  }
  ?>
</main>

<aside>
  <?php
  // displays login form only if user not already logged in
  if(!$user->isLoggedIn()) {
    echo $loginRegister->execute('login');
  }
  ?>
</aside>

When the module is called with execute('register') it will display the registration form, when it would otherwise display the login form. This leaves you to display the login form wherever you'd like, such as in the sidebar via the execute('login') call. However, you'll only want to display the login form if the user is not already logged-in, which is why we put the if(!$user->isLoggedIn()) conditional before it.

Multi-language confirmation emails

The confirmation email is customized in the interactive module configuration in your admin at Modules > Configure > LoginRegisterPro. However, it is just in one language. In a multi-language environment, it may be that you want to tailor the confirmation email to the user’s language. One solution is simply to update the email body text to be presented in multiple languages, not unlike some product manuals. This is a reasonable option because we don't always know the user’s language at this time. But another option is to send the email so that the subject and body are in the user’s language.

In order to send an email in the user’s language, we first need to know their language. As a result, a language selection is something we'd have to add to our Register form. Assuming you already have setup ProcessWire to use multi-language, add the field named "language" to your Register and Profile form fields. Now your registration form will include a language selection.

Next, we need to make the relevant email text fields translatable. In your /site/templates/login-register.php template file (or whatever you have named it), add the following before the $loginRegister->execute() line:

// get the module (you probably already have this line)
$loginRegister = $modules->get('LoginRegisterPro');

// setup translatable text we use in our email
$subject = $this->_('Confirm your registration at {host}');
$intro = $this->_('Please click the link below to confirm the account you requested at {host}:');
$code = $this->_('Confirmation code: {code}');
$click = $this->_('Click to confirm');

// populate translated phrases to LoginRegisterPro
$loginRegister->emailSubject = $subject;
$loginRegister->emailText = "$intro \n\n{url} \n\n$code";
$loginRegister->emailHtml =
  "<html><body>" .
  "<p>$intro</p>" .
  "<p><a href='{url}'>$click</p>" .
  "<p>$code</p>" .
  "</body></html>";

Once you've done this, your settings here will override those in LoginRegisterPro’s module configuration. Now you want to translate the text, so go to Setup > Languages > [each-language] > Add Translatable File, and add the file: /site/templates/login-register.php, then translate the phrases for each language you want to modify the text for. If you want to skip all of this when in the default language then wrap all the code above (except the first line that gets the module) in if(!$user->language->isDefault()) { … } (replacing the ellipsis “…” with the code above).

Register and Profile form fields

Overview of fields

Choose the fields you want to use for both Register and Profile forms in the LoginRegisterPro module configuration. By default, the email and password fields are required for both forms. If you don’t see the fields you want to add, you can create and add them to your “user” template. However, please review what fields are compatible (and not compatible) later in this section.

After a field has been added to the Register or Profile form and saved, you can then click on the field to edit it in the context of either the Register or Profile form. It opens a modal window where you can change things like the label, description and other settings. This enables you to customize the settings specific to the Register or Profile forms independently, without affecting the settings for other usages of the field in your system.

The fields you select do not need to be the same between the forms, but any fields that you made available on your Register form should probably also be available on your Profile form, in case the user wants to later change them. It’s common for the Register form to just contain email and password (and maybe first/last name), while the Profile form contains additional fields that the user can fill out after they have a user account.

Adding fields to your user template

In order to add fields to your Register or Profile forms, they must first be present on the user template. To edit your user template, you’ll want to go to: Setup > Templates, enable the “Filters > Show system templates" toggle, and then you should see template “user” in the “System templates” section. There’s also a link to go directly there in the LoginRegisterPro configuration screen (in both the Register and Profile form descriptions), which may save you a step.

Now editing the “user” template, add the fields you want to be available for your Register and/or Profile forms. Hit Save, and then please remain on the user template edit screen. Scroll to “What fields can a user edit in their own profile?” Check the boxes to make your intended fields editable in the user profile. But note that this is referring to the user profile in the admin (the one that appears if you click your name in the top right corner). If a particular field is going to be editable on the front-end profile screen, then chances are you also want it to be editable in the admin profile screen, so might as well do it now.
Save and return to the LoginRegisterPro module configuration screen. Open the “Register” and “Profile” sections and add the fields that you want to be present in each of these forms.

Known compatible field types

When possible, you should focus on fields using core Fieldtypes for the Register and Profile forms (rather than 3rd party types). Use fields that are primarily text/number <input> or <select> element based. This means that fields using input types of text, textarea, select, checkbox, and radio are generally fine. Others may work as well, but your mileage may vary depending on your front-end environment. Page reference fields and File/Image fields require special considerations, which are covered later in this section—if you intend to use them, be sure to read it all. Below is a list of the types of fields you may use on Register and/or Profile forms (alphabetical):

  • Checkbox
  • Datetime*
  • Email
  • Float
  • Frontend File/Image (Profile form only)
  • Integer
  • Options (Checkboxes, Radios or Select)
  • Page: Multiple (Checkboxes, SelectMultiple, or AsmSelect*)
  • Page: Single (Radios or Select)
  • Text (single language)
  • Textarea (single language, no CKEditor)
  • Toggle
  • URL

*Indicates that jQuery UI may be required for some configurations of this input type.

Other types may also work, but your mileage may vary.

Known not-compatible field types

Below is a list of field types that you will want to avoid because they require an admin environment/theme, make AJAX requests to the admin, accept HTML markup as input, or may not be designed for front-end usage:

  • Repeater (or anything based upon it)
  • CKEditor (or any rich text editor)
  • FieldsetPage
  • Multi-language fields
  • PageTable
  • ProFields
  • PageAutocomplete (Inputfield)
  • PageListSelect (Inputfield)
  • Selector
  • Any field that requires the admin environment/theme
  • Any field that makes AJAX requests to the admin
  • Any field that accepts HTML markup as input

Using Page reference fields

If using any Page reference fields, they let you select the Inputfield type to use. Don’t use Autocomplete or PageListSelect with them. Both of those input types make AJAX requests to the admin, which won’t be accessible to your front-end users. Meaning, they won't work unless the user also has permission to your admin, which of course is not something you want front-end users to have access to. However, it is just fine to use Page reference fields that use Select, Radios, Checkboxes or in many cases AsmSelect, as input types.

Using file and/or image fields

We cannot use ProcessWire’s core file/image fields because they are intended only for input use in an admin environment with trusted users. File uploads require special security considerations (like with FormBuilder), especially because they come from users that can register and create their own account.

For this reason, we've developed a front-end safe file field called “Frontend File” which can be used for file and/or image uploads on the Profile form (files cannot be used on the Register form). This field is provided as a module that you can download from the LoginRegisterPro support board. Once installed, it will be used automatically for any File or Image fields you have added to your Profile form.

While a file/image field designed for front-end usage can make things safer from the technical sense, there are still plenty of risks in using file/image fields, so be sure to read the next section if you intend to use them.

Risks of using file/image fields

Please be aware that there is risk involved any time you have a file-upload field on website form accessible to users that may not necessarily be trusted users. This risk is not unique to LoginRegisterPro, it is a risk for any website or application that lets users upload files.

There are a lot of potential examples where file uploads could be problematic, but let’s look at an obvious one. Let’s say you have an image field where a user can upload a profile photo. Someone registers for an account, logs in, and uploads a photo that is highly inappropriate or even illegal. At that point, your server is hosting that photo. Maybe you are even displaying it to other users in a members list or similar. I don’t think we need to go further, you can see how this might be a problem.

The point is that you need to be aware that having any kind of file upload involves a certain level of risk and responsibility, so you need to be aware of it and consider whether you accept the risk and responsibility.

Module configuration settings

Settings overview

There's a lot of other configuration options for this module and they are grouped in these three sections/fieldsets:

  • Login: settings specific to the front-end login form.
  • Register: registration form settings and confirmation code details.
  • Confirm: settings specific to the confirmation email that is sent to the user.
  • Profile: settings for the profile form available to authenticated users.
  • reCAPTCHA: configuration of Google reCAPTCHA API keys.

The documentation for all of these settings is provided inline on the module configuration screen. Should you have any questions about any specific settings, please ask in the support board. There are however a few settings that would benefit from additional details, and we'll cover those below:

Login > Roles allowed to login on front-end

If no roles are selected then all roles are allowed to login on the front-end. You may prefer to require that admin users login with the admin login form rather than the front-end form. The front-end login form will likely be easy to find on your website, and you may not want to have a form that can login to your admin on the front-end. It’s better for security that your admin login form is not easy to find by automated bots that may use it as a target for dictionary attacks. As a result, whether now or later, you may want to select that only the “login-register” role is allowed to login on the front-end.

Register > Roles to add to newly registered users

When a new user is created through LoginRegisterPro’s registration process, it will receive the selected role(s). LoginRegisterPro creates a unique role named “login-register” for this purpose. This enables you to differentiate users created by LoginRegisterPro from those created by other means in your system. We recommend using this login-register role to start and if you want to later rename it or add more roles, feel free to do so.

Register > Time after which non-confirmed registrations expire

Chances are you will get more registration attempts than actual confirmed registrations. This is because any front-end form is subject to spam submissions, whether automated or manual. As a result, the registration attempts should not be kept around forever, unless you like collecting spam. This setting enables you to delete these from the database after a certain number of seconds pass. Note however that the registration form is protected both by a JS-based honeypot and [optionally] Google reCAPTCHA, so automated registrations are admittedly unlikely.

Profile > Require password for profile changes

As a matter of security, it’s a good idea to ask for the user’s password before allowing them to save changes to certain fields in their Profile. For instance, if someone is going to change their password or email address, you want them to confirm their current password before letting them save changes to their password or email address. Otherwise, if another person comes across a computer with the user logged-in, they could take over the account by changing the password. If a “forgot password” capability is installed, then anyone with access to the account’s email is also able to reset the password. For these reasons we recommend at least having these fields require that the user enter their current password before saving changes in their profile:

  • pass (Set/change password)
  • email (Email address)
  • tfa_type (Two-factor authentication toggle/type, if TFA installed)

Confirm > Email settings

The “from email” address is the one that will be used to send registration confirmation emails to users that register. Both this setting and the “from name” should be recognized by your users as coming from your website. You must also make sure that you are using an email address that your website is allowed to send from, so that it won’t be subject to spam filtering. The email settings also let you select what WireMail module you want to use for sending of these transactional confirmation emails.

API reference

Using the API reference

In this section, all properties and methods are accessed from an instance of the LoginRegisterPro module retrieved like this:

$loginRegister = $modules->get('LoginRegisterPro');
$value = $loginRegister->property; // access a property
$value = $loginRegister->method(); // access a method

Object properties and methods are in the following format:

  • value-type $propertyName
    Description of property.

  • value-type methodName($arguments)
    Description of method.

For methods, when the value-type is void it indicates there is no return value, and when the value-type is self it indicates that the method simply returns the instance of the object it was called on.

Readable properties

  • string $loginUrl
    URL to the login screen or blank if user is already logged-in.

  • string $logoutUrl
    URL to logout or blank if user is not logged-in.

  • string $profileUrl
    URL to edit user’s profile or blank if user is not logged-in.

  • string $registerUrl
    URL to register for a new account or blank if user is already logged-in.

  • string $gravatarUrl
    URL to the Gravatar image, see gravatarUrl() method for options.

  • string $redirectUrl
    URL to redirect to rather than display logged-in action links, use setRedirectUrl method to set.

  • string $url
    Return root LoginRegisterPro URL.

  • bool $userReady
    Returns true if user is authenticated and not editing their profile or logging out. Indicates authenticated user is ready for whatever you are using logged-in users for.

  • array $markup
    Return associative array of current markup settings.

Readable + writable properties

When writing any properties, please do so before calling LoginRegisterPro’s execute() method.

  • string $fromEmail
    Email address that confirmation emails come from.

  • string $fromName
    Name that confirmation emails come from.

  • string $emailSubject
    Subject line to use for confirmation emails.

  • string $emailText
    Plain text email body for confirmation emails.

  • string $emailHtml
    HTML email body for confirmation emails.

Common methods

  • string execute()
    Detect and execute LoginRegisterPro action and return the output.

  • string execute($action)
    Execute given LoginRegisterPro action for non-authenticated users, specify one of: register, login, forgot.

  • string action()
    Detect and return what the current action will be if LoginRegisterPro executes. Returns one of: login, register, forgot, confirm, logout, profile, loggedin.

  • bool userReady()
    Returns true if user is authenticated and not editing their profile or logging out. Indicates authenticated user is ready for whatever you are using logged-in users for.

  • self setRedirectUrl($url)
    Set the URL that should be redirected to when in a “user ready” state (see also userReady above).

Notice/notification methods

  • string renderNotices()
    Render notifications for the current request. Must be called before execute() if you use this, otherwise they are included in the execute() output. It is assumed that you intend to handle the notifications by calling this, so it clears the queue of notices.

  • string getNotices()
    Return an array of notifications (Notice) objects for current request. Must be called before execute() if you use this, otherwise they are included in the execute() output. It is assumed that you intend to handle the notifications by calling this, so it clears the queue of notices.

  • string renderError('your text')
    Render an error notification with the given text.

  • string renderMessage('your text')
    Render a message (success) notification with given text.

  • string renderWarning('your text')
    Render a warning notification with given text.

  • string renderNotice(Notice $notice)
    Render given Notice object, whether NoticeMessage, NoticeError or NoticeWarning.

Other markup methods

  • string renderScripts()
    Render Javascript script links used by LoginRegisterPro. Must be called before execute() if you use this, otherwise they are included in the execute() output.

  • string renderStyles()
    Render CSS link tags used by LoginRegisterPro. Must be called before execute() if you use this, otherwise they are included in the execute() output.

  • self addLink($tag, $name = '')
    Add a link to LoginRegisterPro’s contextual navigation where $tag is full <a href='url'>label</a> markup. Optionally specify a name for the link.

  • self addLink($url, $label, $name = '')
    Add a link to LoginRegisterPro’s contextual navigation, supplying both URL and label. Optionally specify a name for the link.

  • array getLinks()
    Return array of all links contextual to current user state. Array values are <a> tags and keys are link names.

  • string renderLinks()
    Render list of navigation links applicable for current user state.

  • void setMarkup($key, $value)
    Set custom markup for property $key using markup $value. See custom HTML for details.

  • void setMarkup(array $a)
    Set custom markup for multiple custom markup properties where $a is associative array. See custom HTML for details.

URL methods

  • string url($qs = '')
    Return the root LoginRegisterPro URL, optionally with query string $qs, where $qs is string or associative array of query string variables.

  • string loginUrl()
    URL to the login screen or blank if user is already logged-in.

  • string logoutUrl()
    URL to logout or blank if user is not logged-in.

  • string profileUrl()
    URL to edit user’s profile or blank if user is not logged-in.

  • string registerUrl()
    URL to register for a new account or blank if user is already logged-in.

  • string gravatarUrl($rating = 'g', $size = 80, $imageset = 'mm')
    URL to the Gravatar image with optional arguments. The $rating argument can be g, pg, r or x. The $size argument can be any number of pixels and the $imageset argument can be one of: 404, mm, identicon, monsterid, wavatar, retro, or blank.

  • string redirectUrl()
    URL to redirect to rather than display logged-in action links, use setRedirectUrl method to set.

Log methods

  • void logError('your text')
    Log your text to LoginRegisterPro error log.

  • void logMessage('your text')
    Log your text to LoginRegisterPro message log.

Hooks

Almost every aspect of this module is hookable, enabling you to modify or completely replace many methods as needed. If you aren't familiar with using hooks please see the next section below; or if you are already familiar with hooks, you can jump straight to the hooks reference.

How to use hooks

Whether with LoginRegisterPro or anywhere else in ProcessWire, you can hook any method by adding some code to a PHP file (often /site/ready.php) that looks like this:

$wire->addHookBefore('ClassName::methodName', function(HookEvent $event) {
  // hook implementation code
}); 

The addHookBefore(…) above adds a hook before a method is called. This is useful if you want to examine and/or modify the arguments sent to the hooked method, or if you want to perform some action before the hooked method is called… or if you want to optionally prevent the hooked method from being called. On the other hand, if you want to modify the return value of the method, or if you want to perform some action after the hooked method is called, you should instead use addHookAfter(…).

Getting argument values

The arguments sent to the hooked method are available in $event->arguments in order (starting from zero). To get the value of the first argument, you would access $event->arguments(0); or to get the value of the second argument you would access $event->arguments(1); If you prefer, you can also access the arguments by name. For instance, if argument 0 has the name $user, you can get the value of it from $event->arguments('user'); Note however that it is often preferable to get arguments by index order since it's more likely that the names of arguments may change over time than it is that they will change order. Should you decide to use argument names (rather than index numbers), please refer directly to the relevant class code, as the argument names in this documentation may differ from those in the code.

Modifying argument values

When hooking before a method, you can optionally modify the value of any arguments sent to the method by setting a new value to the $event->arguments() call like this: $event->arguments(0, $value); — this would replace the first argument with whatever is in your $value variable. Like with getting arguments, you can also use the argument name rather than index number if you prefer it.

Modifying return value

The return value of the hooked method is available in $event->return if you hooked after the method (addHookAfter). You can get the contents of $event->return by accessing it directly, i.e. $value = $event->return; or you can modify it. by setting it directly, i.e. $event->return = $value;

Preventing hooked method from being called

If you want to prevent the method you hooked from being called, make sure you are substituting and appropriate return value in $event->return. Then add the following somewhere in your hook implementation code: $event->replace = true;

Please continue with the hooks reference below, which begins with an example of much of what has been discussed above.

Hooks reference

Using the hooks reference

In this section, hooks are presented in this format:

  • return-value ClassName::methodName($arguments)
    Description of hook.

To add a hook to any of the following outlined methods, add hook code at the top of your /site/templates/login-register.php template file, before the $loginRegister->execute() call, or if you prefer, you can add it /site/ready.php, where you might already have other hooks. Add the hook to ClassName::methodName part indicated in bold in this hooks reference.

Hook example

In the following example we hook after LoginRegisterPro’s renderError() method to make it return completely different markup than it does by default.

$wire->addHookBefore('LoginRegisterPro::renderError', function($event) {
  // get error text from first argument
  $error = $event->arguments(0);
  // entity encode the error text for HTML output
  $error = $event->sanitizer->entities($error);
  // set the return value
  $event->return = "<div class='uk-alert uk-alert-danger'>$error</div>";
  // prevent the hooked method from being called
  $event->replace = true;
}); 

Note that this hook implementation above is for example purposes only. What it achieves can more efficiently be accomplished with LoginRegisterPro’s custom markup settings and the setMarkup method (see Customization section).

General hooks

  • string LoginRegisterPro::execute()
    Execute LoginRegisterPro and return relevant output. Hook before or after.

  • array LoginRegisterPro::getLinks()
    Returns array of links (markup) that will be displayed to user (indexed by link name). Contextual to whether user is logged-in or not. Hook after this method to modify return value.

  • string LoginRegisterPro::renderLinks()
    Renders the markup for links. Hook after this method to modify returned markup.

  • string LoginRegisterPro::renderError($error)
    Render error message. Hook before to modify $error text or hook after to modify returned markup.

  • string LoginRegisterPro::renderWarning($warning)
    Render warning message. Hook before to modify $warning text or hook after to modify returned markup.

  • string LoginRegisterPro::renderMessage($message)
    Render success message. Hook before to modify $message text or hook after to modify returned markup.

  • string LoginRegisterPro::renderNotice(Notice $notice)
    Render any Notice. Hook before to modify Notice object or hook after to modify returned markup.

  • void LoginRegisterPro::createUserReady(User $user)
    Called before new user is about to be created. Hook before or after (doesn't matter) to modify $user before it is created.

  • void LoginRegisterPro::createdUser(User $user)
    Called after new user has been created. Hook before or after (doesn't matter).

  • string LoginRegisterProCodes::create($length = 40, $method = 'alphanumeric')
    Generates a random confirmation code and returns it.

Login form hooks

  • bool LoginRegisterPro::allowUserLogin(User $user)
    Allow given $user to login through LoginRegisterPro login form? Hook after to analyze or modify return value.

  • void LoginRegisterProLogin::success(User $user)
    Called immediately after a user has successfully logged in. Hook before to obtain the $user.

  • void LoginRegisterProLogin::fail($userName)
    Called when an attempted login has failed. Hook before to obtain the user name.

  • InputfieldForm LoginRegisterProLogin::build()
    Builds the login form. Hook after to modify returned InputfieldForm object or fields within it.

  • InputfieldForm LoginRegisterProLogin::ready(InputfieldForm $form) – Hook called when login form is ready to be rendered or processed. This occurs right before an after(build) hook would occur.

  • string LoginRegisterProLogin::render()
    Renders the login form markup. Hook after to prepend or append something to the markup.

  • string LoginRegisterProLogin::execute()
    Render or process the form and return markup or redirect to self after processing form.

  • bool LoginRegisterProLogin::process()
    Process the login form and return true on success or false on fail. Hook before to perform any action before form processing.

Registration form hooks

  • bool LoginRegisterProRegister::allowRegistration(InputfieldForm $form)
    Allow the submitted $form to be used for a new registration? Hook after to modify return value.

  • void LoginRegisterProRegister::buildConfirmationEmail(WireMail $mail, $emailTo, $confirmCode, $confirmUrl)
    Build and populate the confirmation email body, bodyHTML, subject, fromEmail and fromName to given WireMail $mail object. Hook before to modify arguments or hook after to modify $mail before it is sent.

  • int LoginRegisterProRegister::sendConfirmationEmail($email, $confirmCode)
    Send the confirmation email. Note that this method is what calls the buildConfirmationEmail() method indicated above. This method returns a 0 of mail failed to send or a 1 on success.

  • InputfieldForm LoginRegisterProRegister::build()
    Builds the login form. Hook after to modify returned InputfieldForm object or fields within it.

  • InputfieldForm LoginRegisterProRegister::ready(InputfieldForm $form)
    Hook called when registration form is ready to be rendered or processed. This occurs right before an after(build) hook would occur.

  • string LoginRegisterProRegister::render()
    Renders the registration form markup. Hook after to prepend or append something to the markup.

  • string LoginRegisterProRegister::execute()
    Render or process the registration form and return markup or redirect to self after processing form.

  • bool LoginRegisterProRegister::process()
    Process the registration form and return true on success or false on fail. Hook before to perform any action before form processing.

Confirmation form hooks

  • void LoginRegisterProConfirm::confirmed(User $user)
    Called when a new user has been created as a result of code confirmation. This method performs a redirect, so you should only hook before the method since any after hooks would never get called.

  • InputfieldForm LoginRegisterProConfirm::build()
    Builds the confirmation form. Hook after to modify returned InputfieldForm object or fields within it.

  • InputfieldForm LoginRegisterProConfirm::ready(InputfieldForm $form)
    Hook called when confirmation form is ready to be rendered or processed. This occurs right before an after(build) hook would occur.

  • string LoginRegisterProConfirm::render()
    Renders the confirmation form markup. Hook after to prepend or append something to the markup.

  • string LoginRegisterProConfirm::execute()
    Render or process the confirmation form and return markup or redirect to self after processing form.

  • bool LoginRegisterProConfirm::process()
    Process the confirmation form and return true on success or false on fail. Hook before to perform any action before form processing.

Profile form hooks

  • bool LoginRegisterProProfile::saveReady(User $user, array $changes)
    Called right before a user is about to be saved after submitting the profile form. Return value is true if user has changed or false if not. The $changes argument contains a list of changed field names.

  • void LoginRegisterProProfile::saved(User $user, array $changes)
    Called immediately after $user has been saved after submitting the profile form. The $changes argument contains a list of changed field names.

  • bool LoginRegisterProProfile::emailChangeReady(User $user, $oldEmail, $newEmail)
    Called right before a $user’s email address is about to change. To block the email change a hook can make this method return false.

  • void LoginRegisterProProfile::emailChanged(User $user, $oldEmail, $newEmail)
    Called immediately after an email address has changed.

  • bool LoginRegisterProProfile::deleteUserReady(User $user)
    Called right before a user is deleted as a result of requesting deletion on the profile form. A hook can optionally modify the return value to be false in order to block the deletion.

  • void LoginRegisterProProfile::deletedUser(User $user)
    Called immediately after a user has been deleted as a result of requesting deletion from the profile form.

  • InputfieldForm LoginRegisterProProfile::build()
    Builds the profile edit form. Hook after to modify returned InputfieldForm object or fields within it.

  • InputfieldForm LoginRegisterProProfile::ready(InputfieldForm $form)
    Hook called when profile form is ready to be rendered or processed. This occurs right before an after(build) hook would occur.

  • string LoginRegisterProProfile::render()
    Renders the profile form markup. Hook after to prepend or append something to the markup.

  • string LoginRegisterProProfile::execute()
    Render or process the profile form and return markup or redirect to self after processing form.

  • bool LoginRegisterProProfile::process()
    Process the profile form and return true on success or false on fail. Hook before to perform any action before form processing.

reCAPTCHA hooks

  • string LoginRegisterProRecaptcha::getScriptUrl()
    Returns the URL for Google’s reCAPTCHA service. Hook after to modify the returned URL.

  • string LoginRegisterProRecaptcha::renderScript()
    Renders <script> tag for inserting Google’s reCAPTCHA service.

  • string LoginRegisterProRecaptcha::render()
    Renders reCAPTCHA service div.g-recaptcha element and script (unless script rendered elsewhere).

  • bool LoginRegisterProRecaptcha::process()
    Process reCAPTCHA POST submission and verify with Google reCAPTCHA web service. Returns true on success, false on fail.

Additional topics

Enabling two-factor authentication

If you want to support two-factor authentication, you should install one or more TFA modules to support this. Specifically, I recommend installing the TOTP TFA module as one of the most common and secure ways to provide two-factor authentication. The TFA Email module has also been tested and confirmed working here.

  1. Install and configure (if applicable) one or more TFA modules.

  2. In your admin, go to Modules > Core > Process > Login, and check the box to suggest TFA for the “login-register” role, and any other roles you want to suggest it for.

  3. Go to the LoginRegisterPro module configuration settings (Modules > Site >
    LoginRegisterPro):

    • For the “Login” section “Toggles” field, check the box to “Allow two-factor authentication” (if not already checked).

    • For the “Profile form fields” select the field named tfa_type (“2-factor authentication type”) and save.

  4. Now view the Profile form on the front-end and you should see an option to enable two-factor authentication.

  5. Test out the two-factor authentication to make sure everything is working as you expect. If you encounter any issues, please visit our support forum and/or contact Ryan for help.

Migrating from LoginRegister to LoginRegisterPro

If you are currently using LoginRegister, you should be able to migrate to LoginRegisterPro relatively easily. LoginRegisterPro’s basic API is identical, in that most functions it performs route through the execute() method call, exactly as with LoginRegister. You'd want to install LoginRegisterPro and replace references to LoginRegister with LoginRegisterPro. When you no longer need LoginRegister then you can uninstall and remove it.

One significant difference that you are likely to notice if you've styled anything is that the LoginRegister module wraps all output with <div id='LoginRegister'>…</div> whereas the Pro version wraps output with a <div class='LoginRegisterPro'>…</div>. So if you have targeted the mentioned id attribute in existing CSS or JS, then you'll want to update that to the LoginRegisterPro class attribute instead. Or if you prefer, you can wrap LoginRegisterPro’s output with your own #LoginRegister div.

Where things get really different is when/if you are using any hooks to your LoginRegister module. Because LoginRegisterPro is completely different code, and a much bigger module, it doesn't share any of the hooks that LoginRegister had, and instead it provides a lot more of them, but under different names. So if your migration involves hooks, I'd suggest reviewing the hooks section of this documentation page, and if you have any questions or need help, please post in the LoginRegisterPro support board and paste in your entire hook functions if possible. I can reply with the changes that you'd want to make.

Terms and support

This is a commercial module developed by Ryan Cramer Design, LLC for ProcessWire CMS. You do not haver permission to use this module unless you have purchased it from the ProcessWire store at https://processwire.com/talk/store/. You may not copy or distribute this module, except on site(s) that your chosen license supports (Single, Developer or Agency). It is of course okay to make copies for use on staging or development servers specific to the site you registered for.

Terms and conditions

In no event shall the developers of this module be liable for any special, indirect, consequential, exemplary, or incidental damages whatsoever, including, without limitation, damage for loss of business profits, business interruption, loss of business information, loss of goodwill, or other pecuniary loss whether based in contract, tort, negligence, strict liability, or otherwise, arising out of the use or inability to use this module, even if developers of module have been advised of the possibility of such damages.

This module is provided “as-is” without warranty of any kind, either expressed or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose. The entire risk as to the quality and performance of the program is with you. Should the program prove defective, you assume the cost of all necessary servicing, repair or correction.

The above is what we understand to be necessary legalese for provided software, but please know that should you run into any trouble getting the module to work properly, we are here to help. Please email support or visit the support forum. Support is available at https://processwire.com/talk/ in the LoginRegisterPro VIP support board. You must be logged in with the account you purchased under in order to access the board. You can also contact support by sending a PM in the forums to “ryan”.

Support and upgrades

This service/software includes 1-year of support (and upgrades as available) through the ProcessWire VIP support forum and/or email. The support/upgrades can optionally be renewed on a yearly basis. If your support/upgrades period has already expired and you don't have a renewal invoice, simply send a private message (PM) in the forums to user “ryan” and ask him to reset the renewal invoice or create a new one.

Copyright 2020 by Ryan Cramer

Twitter updates

  • This week a 2nd new module for processing Stripe payments has been added to FormBuilder. Unlike our other Stripe Inputfield, this new one supports 3D Secure (SCA) payments. We’ll take a closer look at it in this post, plus a live demo— More
    16 October 2020
  • Quick weekly update covering this week's commits for the upcoming 3.0.167 ProcessWire core version— More
    18 September 2020
  • This week ProcessWire version 3.0.166 is released on the dev branch. In this post we’ll cover all that’s new relative to the previous version, 3.0.165. Plus we’ll check out the latest new versions of ProCache and FormBuilder— More
    11 September 2020

Latest news

  • ProcessWire Weekly #337
    In the 337th issue of ProcessWire Weekly we're going to introduce a couple of brand new third party modules, take a closer look at the latest core updates, and more. Read on!
    Weekly.pw / 24 October 2020
  • Stripe Payment Processor for FormBuilder
    This week a second new module for processing Stripe payments has been added to FormBuilder. We’ll take a closer look at it in this blog post, plus we’ve got a demo of it here too.
    Blog / 16 October 2020
  • Subscribe to weekly ProcessWire news

“The end client and designer love the ease at which they can update the website. Training beyond how to log in wasn’t even necessary since ProcessWire’s default interface is straightforward.” —Jonathan Lahijani