Tuesday 12 June 2012

Extending Liferay's user registration page

Hello,
    Common task for Liferay is to customize user registraion page. This post I'll describe how you can do it.

    First of all we need to define which fields should be added to registration page.
    In case of these fileds already present in Liferay's database and beans, you should do following in order to add them to registration page:
    1) Create hook plugin and override create_account.jsp into html/portlet/login
    2) Let's add jobTitle property to page, you can do it by adding line:

        to create_account.jsp 
      As you can see we have add Job title field to page. Because of in this case we don't have to modify some java classes it is enough to simply add field to page.

    Now let's assump that we need to add to registration page some special field that is not present into database. In this case we will have to extend some core java classes, so ext-plugin will be used.
    Let's add Hometown filed, field will be store into expando table.
    To add hometown  field to expando do next:
        1) Sign in as Administrator
        2) Go to Control panel - Custom fields - Edit User - Add custom field, fill Key as Home town, save
    Now we have Extended user entity with new filed Hometown.
        3) Set permission for Guest to view and update this value


    So, let's extend registration page with this field.
        1) In ext-plugin override create_account.jsp and add to it:

        2) Into struts-config-ext.xml add:
 
    
    
 

        3) Add class MyCreateAccountAction into /ext-impl/src/com/my/portlet/login/action/ of ext-plugin
 public class MyCreateAccountAction extends CreateAccountAction {

  protected void addUser(
    ActionRequest actionRequest, ActionResponse actionResponse)
   throws Exception {

   HttpServletRequest request = PortalUtil.getHttpServletRequest(
    actionRequest);
   HttpSession session = request.getSession();

   ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
    WebKeys.THEME_DISPLAY);

   Company company = themeDisplay.getCompany();

   boolean autoPassword = true;
   String password1 = null;
   String password2 = null;
   boolean autoScreenName = isAutoScreenName();
   String screenName = ParamUtil.getString(actionRequest, "screenName");
   String emailAddress = ParamUtil.getString(
    actionRequest, "emailAddress");
   long facebookId = ParamUtil.getLong(actionRequest, "facebookId");
   String openId = ParamUtil.getString(actionRequest, "openId");
   String firstName = ParamUtil.getString(actionRequest, "firstName");
   String middleName = ParamUtil.getString(actionRequest, "middleName");
   String lastName = ParamUtil.getString(actionRequest, "lastName");
   int prefixId = ParamUtil.getInteger(actionRequest, "prefixId");
   int suffixId = ParamUtil.getInteger(actionRequest, "suffixId");
   boolean male = ParamUtil.getBoolean(actionRequest, "male", true);
   int birthdayMonth = ParamUtil.getInteger(
    actionRequest, "birthdayMonth");
   int birthdayDay = ParamUtil.getInteger(actionRequest, "birthdayDay");
   int birthdayYear = ParamUtil.getInteger(actionRequest, "birthdayYear");
   String jobTitle = ParamUtil.getString(actionRequest, "jobTitle");
   long[] groupIds = null;
   long[] organizationIds = null;
   long[] roleIds = null;
   long[] userGroupIds = null;
   boolean sendEmail = true;

   ServiceContext serviceContext = ServiceContextFactory.getInstance(
    User.class.getName(), actionRequest);

   if (PropsValues.LOGIN_CREATE_ACCOUNT_ALLOW_CUSTOM_PASSWORD) {
    autoPassword = false;

    password1 = ParamUtil.getString(actionRequest, "password1");
    password2 = ParamUtil.getString(actionRequest, "password2");
   }

   boolean openIdPending = false;

   Boolean openIdLoginPending = (Boolean)session.getAttribute(
    WebKeys.OPEN_ID_LOGIN_PENDING);

   if ((openIdLoginPending != null) &&
    (openIdLoginPending.booleanValue()) &&
    (Validator.isNotNull(openId))) {

    sendEmail = false;
    openIdPending = true;
   }

   User user = UserServiceUtil.addUserWithWorkflow(
    company.getCompanyId(), autoPassword, password1, password2,
    autoScreenName, screenName, emailAddress, facebookId, openId,
    themeDisplay.getLocale(), firstName, middleName, lastName, prefixId,
    suffixId, male, birthdayMonth, birthdayDay, birthdayYear, jobTitle,
    groupIds, organizationIds, roleIds, userGroupIds, sendEmail,
    serviceContext);
   
   // here we are taking home town from request
   String hometown = ParamUtil.getString(actionRequest, "hometown");
   // store home town to expando property
   user.getExpandoBridge().setAttribute("hometown", hometown);
   // get home town from expando property for testing
   System.out.println(user.getExpandoBridge().getAttribute("hometown"));
   

   if (openIdPending) {
    session.setAttribute(
     WebKeys.OPEN_ID_LOGIN, new Long(user.getUserId()));

    session.removeAttribute(WebKeys.OPEN_ID_LOGIN_PENDING);
   }
   else {

    // Session messages

    if (user.getStatus() == WorkflowConstants.STATUS_APPROVED) {
     SessionMessages.add(
      request, "user_added", user.getEmailAddress());
     SessionMessages.add(
      request, "user_added_password",
      user.getPasswordUnencrypted());
    }
    else {
     SessionMessages.add(
      request, "user_pending", user.getEmailAddress());
    }
   }

   // Send redirect

   String login = null;

   if (company.getAuthType().equals(CompanyConstants.AUTH_TYPE_ID)) {
    login = String.valueOf(user.getUserId());
   }
   else if (company.getAuthType().equals(CompanyConstants.AUTH_TYPE_SN)) {
    login = user.getScreenName();
   }
   else {
    login = user.getEmailAddress();
   }

   sendRedirect(
    actionRequest, actionResponse, themeDisplay, login,
    user.getPasswordUnencrypted());
  }
 }

That is it, we have extended page and action.
Complete sources you can find here and here.
  
BR,
Paul

4 comments:

  1. I add a custom field in create_account.jsp
    like this:


    It only shows a label "Country" without input box on the page? Thank you!

    ReplyDelete
  2. The html codes can't seen.
    aui:input model="<%= User.class %>" name="middleName"

    ReplyDelete
  3. if i use
    aui:input model="<%= User.class %>" name="jobTitle"
    . It's ok, the input box shows

    ReplyDelete
  4. where should we put the struts-config-ext.xml?

    ReplyDelete