Skip to content
Snippets Groups Projects
ProfileFormController.java 13.02 KiB
/**
 * <a href="http://www.openolat.org">
 * OpenOLAT - Online Learning and Training</a><br>
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); <br>
 * you may not use this file except in compliance with the License.<br>
 * You may obtain a copy of the License at the
 * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
 * <p>
 * Unless required by applicable law or agreed to in writing,<br>
 * software distributed under the License is distributed on an "AS IS" BASIS, <br>
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
 * See the License for the specific language governing permissions and <br>
 * limitations under the License.
 * <p>
 * Initial code contributed and copyrighted by<br>
 * frentix GmbH, http://www.frentix.com
 * <p>
 */

package org.olat.user;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.form.flexible.FormItem;
import org.olat.core.gui.components.form.flexible.FormItemContainer;
import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
import org.olat.core.gui.components.form.flexible.elements.RichTextElement;
import org.olat.core.gui.components.form.flexible.elements.TextElement;
import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
import org.olat.core.gui.components.velocity.VelocityContainer;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.id.Identity;
import org.olat.core.id.User;
import org.olat.core.util.xml.XStreamHelper;
import org.olat.registration.RegistrationManager;
import org.olat.registration.TemporaryKeyImpl;
import org.olat.user.propertyhandlers.UserPropertyHandler;

import com.thoughtworks.xstream.XStream;

/**
 * Provides a controller which lets the user edit their user profile and choose
 * the fields which are made publicly visible.
 * 
 * @author twuersch
 * 
 */
public class ProfileFormController extends FormBasicController {

	private HomePageConfig conf;

	private List<UserPropertyHandler> userPropertyHandlers;

	private Map<String, FormItem> formItems;

	private Map<String, String> formContext;

	private RichTextElement textAboutMe;

	private String usageIdentifier;

	private Map<String, MultipleSelectionElement> publishCheckboxes;

	private Identity identity;

	private boolean isAdministrativeUser;


	/**
	 * Creates this controller.
	 * 
	 * @param ureq The user request.
	 * @param wControl The window control.
	 * @param conf The homepage configuration (decides which user profile fields
	 *          are visible for everyone).
	 * @param identity The identity of the user.
	 * @param isAdministrativeUser true: user is editing another users profile as
	 *          user manager; false: use is editing his own profile
	 */
	public ProfileFormController(UserRequest ureq, WindowControl wControl, HomePageConfig conf, Identity identity,
			boolean isAdministrativeUser) {
		super(ureq, wControl, "combinedform");
		UserManager um = UserManager.getInstance();
		setTranslator(um.getPropertyHandlerTranslator(getTranslator()));		
		this.publishCheckboxes = new HashMap<String, MultipleSelectionElement>();
		this.conf = conf;
		this.usageIdentifier = ProfileFormController.class.getCanonicalName();
		this.userPropertyHandlers = um.getUserPropertyHandlersFor(this.usageIdentifier, isAdministrativeUser);
		this.identity = identity;
		this.formItems = new HashMap<String, FormItem>();
		this.formContext = new HashMap<String, String>();
		this.isAdministrativeUser = isAdministrativeUser;
		initForm(ureq);
	}

	/**
	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#doDispose()
	 */
	@Override
	protected void doDispose() {
	// nothing to dispose.

	}

	/**
	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#formOK(org.olat.core.gui.UserRequest)
	 */
	@Override
	protected void formOK(UserRequest ureq) {
		fireEvent(ureq, Event.DONE_EVENT);
	}

	/**
	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#formNOK(org.olat.core.gui.UserRequest)
	 */
	@Override
	protected void formNOK(UserRequest ureq) {
		fireEvent(ureq, Event.FAILED_EVENT);
	}

	/**
	 * @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#formCancelled(org.olat.core.gui.UserRequest)
	 */
	@Override
	protected void formCancelled(UserRequest ureq) {
		fireEvent(ureq, Event.CANCELLED_EVENT);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.olat.core.gui.components.form.flexible.impl.FormBasicController#initForm
	 * (org.olat.core.gui.components.form.flexible.FormItemContainer,
	 * org.olat.core.gui.control.Controller, org.olat.core.gui.UserRequest)
	 */
	@Override
	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
		formContext.put("username", identity.getName());
		
		String currentGroup = null;
		List<UserPropertyHandler> homepagePropertyHanders = UserManager.getInstance().getUserPropertyHandlersFor(HomePageConfig.class.getCanonicalName(), isAdministrativeUser);
		// show a form element for each property handler 
		FormLayoutContainer groupContainer = null;
		for (UserPropertyHandler userPropertyHandler : this.userPropertyHandlers) {
			if (userPropertyHandler == null) {
				continue;
			}
			
			// add spacer if necessary (i.e. when group name changes)
			String group = userPropertyHandler.getGroup();
			if (!group.equals(currentGroup)) {
				groupContainer = FormLayoutContainer.createDefaultFormLayout("group." + group, getTranslator());
				groupContainer.setFormTitle(translate("form.group." + group));
				this.formItems.put("group." + group, groupContainer);
				formLayout.add(groupContainer);
				currentGroup = group;
			}
			
//			if (homepagePropertyHanders.contains(userPropertyHandler)) {
//				// add checkbox to container if configured for homepage usage identifier
//				String checkboxName = "checkbox_" + userPropertyHandler.getName();
//				MultipleSelectionElement publishCheckbox = uifactory.addCheckboxesHorizontal(checkboxName, null, groupContainer, new String[] {userPropertyHandler.i18nFormElementLabelKey()}, new String[] {""}, null);
//				this.publishCheckboxes.put(checkboxName, publishCheckbox);
//				boolean isEnabled = this.conf.isEnabled(userPropertyHandler.getName());
//				if (isEnabled) {
//					publishCheckbox.select(userPropertyHandler.i18nFormElementLabelKey(), true);
//				} else {
//					publishCheckbox.select(userPropertyHandler.i18nFormElementLabelKey(), false);
//				}				
//				// Mandatory homepage properties can not be changed by user
//				UserManager um = UserManager.getInstance();
//				if (um.isMandatoryUserProperty(HomePageConfig.class.getCanonicalName(), userPropertyHandler)) {
//					publishCheckbox.select(userPropertyHandler.i18nFormElementLabelKey(), true);
//					publishCheckbox.setEnabled(false);
//				}
//			} else {
//				uifactory.addSpacerElement("spacer_" + userPropertyHandler.getName(), groupContainer, true);
//			}
			
			// add input field to container
			FormItem formItem = userPropertyHandler.addFormItem(getLocale(), identity.getUser(), this.usageIdentifier, this.isAdministrativeUser, groupContainer);
			String propertyName = userPropertyHandler.getName();
			this.formItems.put(propertyName, formItem);
			
			if (formItem instanceof TextElement) {
				// it's a text field, so get the value of this property into the text field
				TextElement textElement = (TextElement)formItem;
				textElement.setValue(this.identity.getUser().getProperty(propertyName, getLocale()));
			} else if (formItem instanceof MultipleSelectionElement) {
				// it's a checkbox, so set the box to checked if the corresponding property is set to "true"
				MultipleSelectionElement checkbox = (MultipleSelectionElement)formItem;
				String value = this.identity.getUser().getProperty(propertyName, getLocale());
				if (value != null) {
					checkbox.select(propertyName, value.equals("true"));
				} else {
					// assume "false" if the property is not present
					checkbox.select(propertyName, false);
				}
			}
			
			// special case for email field
			if (userPropertyHandler.getName().equals("email")) {
				RegistrationManager rm = RegistrationManager.getInstance();
				String key = this.identity.getUser().getProperty("emchangeKey", null);
				TemporaryKeyImpl tempKey = rm.loadTemporaryKeyByRegistrationKey(key);
				if (tempKey != null) {
					XStream xml = XStreamHelper.createXStreamInstance();
					@SuppressWarnings("unchecked")
					HashMap<String, String> mails = (HashMap<String, String>) xml.fromXML(tempKey.getEmailAddress());
					formItem.setExampleKey("email.change.form.info", new String[] {mails.get("changedEMail")});
				}
			}
		}
		
		// add the "about me" text field.
		groupContainer = FormLayoutContainer.createDefaultFormLayout("group.about", getTranslator());
		groupContainer.setFormTitle(translate("form.group.about"));
		this.formItems.put("group.about", groupContainer);
		formLayout.add(groupContainer);

		textAboutMe = uifactory.addRichTextElementForStringData("form.text", "form.text", this.conf.getTextAboutMe(), 10, -1, false, null, null, groupContainer, ureq.getUserSession(), getWindowControl());
		textAboutMe.setMaxLength(10000);
		formItems.put("form.text", this.textAboutMe);
		
		// Create submit and cancel buttons
		FormLayoutContainer buttonLayoutWrappper = FormLayoutContainer.createDefaultFormLayout("buttonLayoutWrappper", getTranslator());
		formLayout.add(buttonLayoutWrappper);
		FormLayoutContainer buttonLayout = FormLayoutContainer.createButtonLayout("buttonLayoutInner", getTranslator());
		buttonLayoutWrappper.add(buttonLayout);
		uifactory.addFormSubmitButton("save", buttonLayout);
		uifactory.addFormCancelButton("cancel", buttonLayout, ureq, getWindowControl());
		formItems.put("buttonLayout", buttonLayout);
		
		Set<String> userPropertyNames = formItems.keySet();
		((VelocityContainer)this.flc.getComponent()).contextPut("userPropertyNames", userPropertyNames);
	}

	/**
	 * Stores the data from the form into a) the user's home page configuration
	 * and b) the user's properties.
	 * 
	 * @param config The user's home page configuration (i.e. flags for publicly
	 *          visible fields).
	 * @param identity The user's identity
	 */
	public void updateFromFormData(final HomePageConfig config, final Identity identity) {
		User user = identity.getUser();
		// For each user property...
		for (UserPropertyHandler userPropertyHandler : this.userPropertyHandlers) {

			// ...get the value from the form field and store it into the user
			// property...
			FormItem formItem = this.formItems.get(userPropertyHandler.getName());

			userPropertyHandler.updateUserFromFormItem(user, formItem);

			// ...and store the "publish" flag for each property.
			MultipleSelectionElement checkbox = this.publishCheckboxes.get("checkbox_" + userPropertyHandler.getName());
			if (checkbox != null) {
				// null when not enabled for the org.olat.user.HomePageConfig usage
				// identifier key
				if (checkbox.getSelectedKeys().size() == 0) {
					config.setEnabled(userPropertyHandler.getName(), false);
				} else {
					config.setEnabled(userPropertyHandler.getName(), true);
				}
			}
		}
		// Store the "about me" text.
		conf.setTextAboutMe(textAboutMe.getValue());
	}

	/**
	 * Take form data and set it in the user fields for the current subject
	 * 
	 * @param id The identity to be updated (transient, does not do any db calls)
	 * @return the updated identity object
	 */
	public Identity updateIdentityFromFormData(Identity id) {
		identity = id;
		User user = identity.getUser();
		// update each user field
		for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) {
			FormItem formItem = formItems.get(userPropertyHandler.getName());
			userPropertyHandler.updateUserFromFormItem(user, formItem);
		}
		return identity;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seeorg.olat.core.gui.components.form.flexible.impl.FormBasicController#
	 * validateFormLogic(org.olat.core.gui.UserRequest)
	 */
	@Override
	protected boolean validateFormLogic(UserRequest ureq) {
		boolean formOK = true;
		User user = identity.getUser();
		for (UserPropertyHandler userPropertyHandler : this.userPropertyHandlers) {
			FormItem formItem = formItems.get(userPropertyHandler.getName());
			if (!userPropertyHandler.isValid(user, formItem, formContext)) {
				formOK = false;
			} else {
				formItem.clearError();
			}
		}
		
		try {
			String aboutMe = textAboutMe.getValue();
			if(aboutMe.length() > 10000) {
				textAboutMe.setErrorKey("input.toolong", new String[] {"10000"});
				formOK = false;
			} else {
				textAboutMe.clearError();
			}
		} catch (Exception e) {
			textAboutMe.setErrorKey("input.toolong", new String[] {"10000"});
			formOK = false;
		}
		return formOK && super.validateFormLogic(ureq);
	}

	/**
	 * Sets the dirty mark for this form.
	 * 
	 * @param isDirtyMarking <code>true</code> sets this form dirty.
	 */
	public void setDirtyMarking(boolean isDirtyMarking) {
		mainForm.setDirtyMarking(isDirtyMarking);
	}
}