/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This file is part of Liferay Social Office. Liferay Social Office is free
* software: you can redistribute it and/or modify it under the terms of the GNU
* Affero General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* Liferay Social Office is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along with
* Liferay Social Office. If not, see http://www.gnu.org/licenses/agpl-3.0.html.
*/
package com.liferay.so.sites.portlet;
import com.liferay.portal.kernel.exception.DuplicateGroupException;
import com.liferay.portal.kernel.exception.GroupKeyException;
import com.liferay.portal.kernel.json.JSONArray;
import com.liferay.portal.kernel.json.JSONFactoryUtil;
import com.liferay.portal.kernel.json.JSONObject;
import com.liferay.portal.kernel.language.LanguageUtil;
import com.liferay.portal.kernel.model.Group;
import com.liferay.portal.kernel.model.Layout;
import com.liferay.portal.kernel.model.LayoutConstants;
import com.liferay.portal.kernel.model.LayoutSet;
import com.liferay.portal.kernel.model.LayoutSetPrototype;
import com.liferay.portal.kernel.model.MembershipRequest;
import com.liferay.portal.kernel.model.MembershipRequestConstants;
import com.liferay.portal.kernel.model.Organization;
import com.liferay.portal.kernel.model.User;
import com.liferay.portal.kernel.model.UserGroup;
import com.liferay.portal.kernel.portlet.LiferayPortletResponse;
import com.liferay.portal.kernel.portlet.PortletProvider;
import com.liferay.portal.kernel.portlet.PortletProviderUtil;
import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet;
import com.liferay.portal.kernel.security.permission.ActionKeys;
import com.liferay.portal.kernel.security.permission.PermissionChecker;
import com.liferay.portal.kernel.service.GroupLocalServiceUtil;
import com.liferay.portal.kernel.service.GroupServiceUtil;
import com.liferay.portal.kernel.service.LayoutLocalServiceUtil;
import com.liferay.portal.kernel.service.LayoutSetLocalServiceUtil;
import com.liferay.portal.kernel.service.LayoutSetPrototypeServiceUtil;
import com.liferay.portal.kernel.service.MembershipRequestLocalServiceUtil;
import com.liferay.portal.kernel.service.OrganizationLocalServiceUtil;
import com.liferay.portal.kernel.service.PortletPreferencesLocalServiceUtil;
import com.liferay.portal.kernel.service.ServiceContext;
import com.liferay.portal.kernel.service.ServiceContextFactory;
import com.liferay.portal.kernel.service.UserGroupLocalServiceUtil;
import com.liferay.portal.kernel.service.UserLocalServiceUtil;
import com.liferay.portal.kernel.service.permission.GroupPermissionUtil;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.util.ClassResolverUtil;
import com.liferay.portal.kernel.util.Constants;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.HtmlUtil;
import com.liferay.portal.kernel.util.MethodKey;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.portal.kernel.util.PortalClassInvoker;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.UnicodeProperties;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.so.service.FavoriteSiteLocalServiceUtil;
import com.liferay.so.service.SocialOfficeServiceUtil;
import com.liferay.so.sites.util.SitesUtil;
import com.liferay.so.util.GroupConstants;
import com.liferay.so.util.PortletKeys;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import javax.portlet.PortletPreferences;
import javax.portlet.PortletRequest;
import javax.portlet.PortletURL;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import javax.portlet.WindowState;
/**
* @author Ryan Park
* @author Jonathan Lee
* @author Evan Thibodeau
*/
public class SitesPortlet extends MVCPortlet {
public void addSite(
ActionRequest actionRequest, ActionResponse actionResponse)
throws Exception {
String redirect = ParamUtil.getString(actionRequest, "redirect");
if (Validator.isNotNull(redirect)) {
doAddSite(actionRequest, actionResponse);
}
else {
JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
try {
doAddSite(actionRequest, actionResponse);
jsonObject.put("result", "success");
}
catch (Exception e) {
jsonObject.put("result", "failure");
String message = null;
if (e instanceof DuplicateGroupException) {
message = "please-enter-a-unique-name";
}
else if (e instanceof GroupKeyException) {
message = "please-enter-a-valid-name";
}
else {
message = "your-request-failed-to-complete";
}
ThemeDisplay themeDisplay =
(ThemeDisplay)actionRequest.getAttribute(
WebKeys.THEME_DISPLAY);
jsonObject.put("message", themeDisplay.translate(message));
}
writeJSON(actionRequest, actionResponse, jsonObject);
}
}
public void getLayoutSetPrototypeDescription(
ResourceRequest resourceRequest, ResourceResponse resourceResponse)
throws Exception {
ThemeDisplay themeDisplay = (ThemeDisplay)resourceRequest.getAttribute(
WebKeys.THEME_DISPLAY);
int layoutSetPrototypeId = ParamUtil.getInteger(
resourceRequest, "layoutSetPrototypeId");
JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
if (layoutSetPrototypeId <= 0) {
jsonObject.put("description", StringPool.BLANK);
jsonObject.put("layoutSetPrototypeId", layoutSetPrototypeId);
jsonObject.put("name", themeDisplay.translate("none"));
JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
jsonObject.put("layouts", jsonArray);
}
else {
LayoutSetPrototype layoutSetPrototype =
LayoutSetPrototypeServiceUtil.getLayoutSetPrototype(
layoutSetPrototypeId);
jsonObject.put("description", layoutSetPrototype.getDescription());
jsonObject.put("layoutSetPrototypeId", layoutSetPrototypeId);
jsonObject.put(
"name", layoutSetPrototype.getName(themeDisplay.getLocale()));
JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
Group layoutSetPrototypeGroup = layoutSetPrototype.getGroup();
List<Layout> layouts = LayoutLocalServiceUtil.getLayouts(
layoutSetPrototypeGroup.getGroupId(), true, 0);
for (Layout layout : layouts) {
JSONObject layoutJSONObject =
JSONFactoryUtil.createJSONObject();
layoutJSONObject.put("layoutId", layout.getLayoutId());
layoutJSONObject.put(
"name", layout.getName(themeDisplay.getLocale()));
jsonArray.put(layoutJSONObject);
}
jsonObject.put("layouts", jsonArray);
}
writeJSON(resourceRequest, resourceResponse, jsonObject);
}
public void getSites(
ResourceRequest resourceRequest, ResourceResponse resourceResponse)
throws Exception {
ThemeDisplay themeDisplay = (ThemeDisplay)resourceRequest.getAttribute(
WebKeys.THEME_DISPLAY);
boolean directory = ParamUtil.getBoolean(resourceRequest, "directory");
int end = ParamUtil.getInteger(resourceRequest, "end", 10);
String keywords = ParamUtil.getString(resourceRequest, "keywords");
int maxResultSize = ParamUtil.getInteger(
resourceRequest, "maxResultSize", 10);
String searchTab = ParamUtil.getString(resourceRequest, "searchTab");
int start = ParamUtil.getInteger(resourceRequest, "start");
updateUserPreferences(themeDisplay, searchTab);
JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
JSONObject optionsJSONObject = JSONFactoryUtil.createJSONObject();
optionsJSONObject.put("directory", directory);
optionsJSONObject.put("end", end);
optionsJSONObject.put("keywords", keywords);
optionsJSONObject.put("maxResultSize", maxResultSize);
optionsJSONObject.put("searchTab", searchTab);
optionsJSONObject.put("start", start);
jsonObject.put("options", optionsJSONObject);
List<Group> groups = null;
int groupsCount = 0;
if (searchTab.equals("my-sites")) {
groups = SitesUtil.getVisibleSites(
themeDisplay.getCompanyId(), themeDisplay.getUserId(), keywords,
true, start, end);
groupsCount = SitesUtil.getVisibleSitesCount(
themeDisplay.getCompanyId(), themeDisplay.getUserId(), keywords,
true);
}
else if (searchTab.equals("my-favorites")) {
groups = SitesUtil.getFavoriteSitesGroups(
themeDisplay.getUserId(), keywords, start, end);
groupsCount = SitesUtil.getFavoriteSitesGroupsCount(
themeDisplay.getUserId(), keywords);
}
else {
groups = SitesUtil.getVisibleSites(
themeDisplay.getCompanyId(), themeDisplay.getUserId(), keywords,
false, start, end);
groupsCount = SitesUtil.getVisibleSitesCount(
themeDisplay.getCompanyId(), themeDisplay.getUserId(), keywords,
false);
}
jsonObject.put("count", groupsCount);
LiferayPortletResponse liferayPortletResponse =
(LiferayPortletResponse)resourceResponse;
JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
for (Group group : groups) {
JSONObject groupJSONObject = JSONFactoryUtil.createJSONObject();
groupJSONObject.put(
"description", HtmlUtil.escape(group.getDescription()));
groupJSONObject.put(
"name",
HtmlUtil.escape(
group.getDescriptiveName(themeDisplay.getLocale())));
boolean member = GroupLocalServiceUtil.hasUserGroup(
themeDisplay.getUserId(), group.getGroupId());
if (group.hasPrivateLayouts() && member) {
groupJSONObject.put(
"privateLayoutsURL",
group.getDisplayURL(themeDisplay, true));
}
if (group.hasPublicLayouts()) {
groupJSONObject.put(
"publicLayoutsURL",
group.getDisplayURL(themeDisplay, false));
}
boolean socialOfficeGroup =
SocialOfficeServiceUtil.isSocialOfficeGroup(group.getGroupId());
groupJSONObject.put("socialOfficeGroup", socialOfficeGroup);
PortletURL siteAssignmentsPortletURL =
PortletProviderUtil.getPortletURL(
resourceRequest, MembershipRequest.class.getName(),
PortletProvider.Action.EDIT);
siteAssignmentsPortletURL.setParameter(
"redirect", themeDisplay.getURLCurrent());
siteAssignmentsPortletURL.setParameter(
"groupId", String.valueOf(group.getGroupId()));
siteAssignmentsPortletURL.setWindowState(WindowState.NORMAL);
PermissionChecker permissionChecker =
themeDisplay.getPermissionChecker();
if (!member && (group.getType() == GroupConstants.TYPE_SITE_OPEN)) {
siteAssignmentsPortletURL.setParameter(
"addUserIds", String.valueOf(themeDisplay.getUserId()));
groupJSONObject.put(
"joinURL", siteAssignmentsPortletURL.toString());
}
else if (!member &&
(group.getType() == GroupConstants.TYPE_SITE_RESTRICTED)) {
if (!MembershipRequestLocalServiceUtil.hasMembershipRequest(
themeDisplay.getUserId(), group.getGroupId(),
MembershipRequestConstants.STATUS_PENDING)) {
PortletURL membershipRequestURL =
liferayPortletResponse.createActionURL(
PortletKeys.SITE_ADMIN);
membershipRequestURL.setParameter(
"javax.portlet.action", "postMembershipRequest");
membershipRequestURL.setParameter(
"redirect", themeDisplay.getURLCurrent());
membershipRequestURL.setParameter(
"groupId", String.valueOf(group.getGroupId()));
User user = UserLocalServiceUtil.getUser(
themeDisplay.getUserId());
String comments = LanguageUtil.format(
themeDisplay.getLocale(), "x-wishes-to-join-x",
new Object[] {
user.getFullName(), group.getDescriptiveName()
},
false);
membershipRequestURL.setParameter("comments", comments);
membershipRequestURL.setWindowState(WindowState.NORMAL);
groupJSONObject.put(
"requestUrl", membershipRequestURL.toString());
}
else {
groupJSONObject.put("membershipRequested", true);
}
}
else if (member &&
!isOrganizationOrUserGroupMember(
themeDisplay.getUserId(), group)) {
siteAssignmentsPortletURL.setParameter(
"removeUserIds", String.valueOf(themeDisplay.getUserId()));
if ((group.getType() != GroupConstants.TYPE_SITE_PRIVATE) ||
GroupPermissionUtil.contains(
permissionChecker, group.getGroupId(),
ActionKeys.ASSIGN_MEMBERS)) {
groupJSONObject.put(
"leaveURL", siteAssignmentsPortletURL.toString());
}
}
if (GroupPermissionUtil.contains(
permissionChecker, group.getGroupId(), ActionKeys.DELETE)) {
if (group.getGroupId() == themeDisplay.getSiteGroupId()) {
groupJSONObject.put("deleteURL", StringPool.FALSE);
}
else {
PortletURL deletePortletURL =
liferayPortletResponse.createActionURL(
PortletKeys.SITE_ADMIN);
deletePortletURL.setParameter(
"javax.portlet.action", "deleteGroups");
deletePortletURL.setParameter(
"redirect", themeDisplay.getURLCurrent());
deletePortletURL.setParameter(
"groupId", String.valueOf(group.getGroupId()));
deletePortletURL.setWindowState(WindowState.NORMAL);
groupJSONObject.put(
"deleteURL", deletePortletURL.toString());
}
}
PortletURL favoritePortletURL = resourceResponse.createActionURL();
favoritePortletURL.setParameter(
ActionRequest.ACTION_NAME, "updateFavorites");
favoritePortletURL.setParameter(
"redirect", themeDisplay.getURLCurrent());
favoritePortletURL.setParameter(
"groupId", String.valueOf(group.getGroupId()));
favoritePortletURL.setWindowState(WindowState.NORMAL);
if (!member && !group.hasPublicLayouts()) {
groupJSONObject.put("favoriteURL", StringPool.BLANK);
}
else {
if (!FavoriteSiteLocalServiceUtil.isFavoriteSite(
themeDisplay.getUserId(), group.getGroupId())) {
favoritePortletURL.setParameter(
Constants.CMD, Constants.ADD);
groupJSONObject.put(
"favoriteURL", favoritePortletURL.toString());
}
else {
favoritePortletURL.setParameter(
Constants.CMD, Constants.DELETE);
groupJSONObject.put(
"unfavoriteURL", favoritePortletURL.toString());
}
}
jsonArray.put(groupJSONObject);
}
jsonObject.put("sites", jsonArray);
writeJSON(resourceRequest, resourceResponse, jsonObject);
}
public void hideNotice(
ActionRequest actionRequest, ActionResponse actionResponse)
throws Exception {
ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
WebKeys.THEME_DISPLAY);
User user = themeDisplay.getUser();
Group group = user.getGroup();
PortletPreferences portletPreferences =
PortletPreferencesLocalServiceUtil.getPreferences(
user.getCompanyId(), group.getGroupId(),
PortletKeys.PREFS_OWNER_TYPE_GROUP, 0, "5_WAR_soportlet");
portletPreferences.setValue("hide-notice", Boolean.TRUE.toString());
portletPreferences.store();
}
@Override
public void processAction(
ActionRequest actionRequest, ActionResponse actionResponse)
throws PortletException {
try {
String actionName = ParamUtil.getString(
actionRequest, ActionRequest.ACTION_NAME);
if (actionName.equals("addSite")) {
addSite(actionRequest, actionResponse);
}
else {
super.processAction(actionRequest, actionResponse);
}
}
catch (Exception e) {
throw new PortletException(e);
}
}
@Override
public void serveResource(
ResourceRequest resourceRequest, ResourceResponse resourceResponse)
throws PortletException {
try {
String resourceID = resourceRequest.getResourceID();
if (resourceID.equals("getLayoutSetPrototypeDescription")) {
getLayoutSetPrototypeDescription(
resourceRequest, resourceResponse);
}
else if (resourceID.equals("getSites")) {
getSites(resourceRequest, resourceResponse);
}
else {
super.serveResource(resourceRequest, resourceResponse);
}
}
catch (Exception e) {
throw new PortletException(e);
}
}
public void updateFavorites(
ActionRequest actionRequest, ActionResponse actionResponse)
throws Exception {
ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
WebKeys.THEME_DISPLAY);
String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
long groupId = ParamUtil.getLong(actionRequest, "groupId");
JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
try {
if (cmd.equals(Constants.ADD)) {
FavoriteSiteLocalServiceUtil.addFavoriteSite(
themeDisplay.getUserId(), groupId);
}
else if (cmd.equals(Constants.DELETE)) {
FavoriteSiteLocalServiceUtil.deleteFavoriteSites(
themeDisplay.getUserId(), groupId);
}
}
catch (Exception e) {
jsonObject.put("result", "failure");
writeJSON(actionRequest, actionResponse, jsonObject);
return;
}
jsonObject.put("result", "success");
writeJSON(actionRequest, actionResponse, jsonObject);
}
protected void doAddSite(
ActionRequest actionRequest, ActionResponse actionResponse)
throws Exception {
ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
WebKeys.THEME_DISPLAY);
Map<Locale, String> nameMap = new HashMap<>();
String name = ParamUtil.getString(actionRequest, "name");
nameMap.put(themeDisplay.getLocale(), name);
Map<Locale, String> descriptionMap = new HashMap<>();
String description = ParamUtil.getString(actionRequest, "description");
descriptionMap.put(themeDisplay.getLocale(), description);
long layoutSetPrototypeId = ParamUtil.getLong(
actionRequest, "layoutSetPrototypeId");
int type = ParamUtil.getInteger(actionRequest, "type");
boolean privateLayout = false;
if (type == GroupConstants.TYPE_SITE_PRIVATE_RESTRICTED) {
type = GroupConstants.TYPE_SITE_RESTRICTED;
privateLayout = true;
}
else if (type == GroupConstants.TYPE_SITE_PUBLIC_RESTRICTED) {
type = GroupConstants.TYPE_SITE_RESTRICTED;
}
else if (type == GroupConstants.TYPE_SITE_PRIVATE) {
privateLayout = true;
}
ServiceContext serviceContext = ServiceContextFactory.getInstance(
Group.class.getName(), actionRequest);
Group group = GroupServiceUtil.addGroup(
GroupConstants.DEFAULT_PARENT_GROUP_ID,
GroupConstants.DEFAULT_LIVE_GROUP_ID, nameMap, descriptionMap, type,
true, GroupConstants.DEFAULT_MEMBERSHIP_RESTRICTION,
StringPool.BLANK, true, true, serviceContext);
long publicLayoutSetPrototypeId = 0;
long privateLayoutSetPrototypeId = 0;
if (privateLayout) {
privateLayoutSetPrototypeId = layoutSetPrototypeId;
}
else {
publicLayoutSetPrototypeId = layoutSetPrototypeId;
}
PortalClassInvoker.invoke(
_updateLayoutSetPrototypesMethodKey, group,
publicLayoutSetPrototypeId, privateLayoutSetPrototypeId,
!privateLayout, privateLayout);
LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
group.getGroupId(), privateLayout);
PortalClassInvoker.invoke(
_mergeLayoutSetPrototypeLayoutsMethodKey, group, layoutSet);
long[] deleteLayoutIds = getLongArray(actionRequest, "deleteLayoutIds");
List<Layout> layouts = new ArrayList<>(deleteLayoutIds.length);
for (long deleteLayoutId : deleteLayoutIds) {
Layout layout = LayoutLocalServiceUtil.getLayout(
group.getGroupId(), privateLayout, deleteLayoutId);
layouts.add(layout);
}
for (Layout layout : layouts) {
LayoutLocalServiceUtil.deleteLayout(layout, true, serviceContext);
}
setCustomJspServletContextName(group);
}
protected long[] getLongArray(PortletRequest portletRequest, String name) {
String value = portletRequest.getParameter(name);
if (value == null) {
return null;
}
return StringUtil.split(GetterUtil.getString(value), 0L);
}
protected boolean isOrganizationOrUserGroupMember(long userId, Group group)
throws Exception {
if (group.isOrganization()) {
return true;
}
List<Organization> organizations =
OrganizationLocalServiceUtil.getGroupOrganizations(
group.getGroupId());
for (Organization organization : organizations) {
if (OrganizationLocalServiceUtil.hasUserOrganization(
userId, organization.getOrganizationId())) {
return true;
}
}
List<UserGroup> userGroups =
UserGroupLocalServiceUtil.getGroupUserGroups(group.getGroupId());
for (UserGroup userGroup : userGroups) {
if (UserGroupLocalServiceUtil.hasUserUserGroup(
userId, userGroup.getUserGroupId())) {
return true;
}
}
return false;
}
protected void setCustomJspServletContextName(Group group)
throws Exception {
UnicodeProperties typeSettingsProperties =
group.getTypeSettingsProperties();
typeSettingsProperties.setProperty(
"customJspServletContextName", "so-hook");
GroupLocalServiceUtil.updateGroup(
group.getGroupId(), typeSettingsProperties.toString());
}
protected void updateUserPreferences(
ThemeDisplay themeDisplay, String searchTab)
throws Exception {
PortletPreferences portletPreferences =
PortletPreferencesLocalServiceUtil.getPreferences(
themeDisplay.getCompanyId(), themeDisplay.getUserId(),
PortletKeys.PREFS_OWNER_TYPE_USER, LayoutConstants.DEFAULT_PLID,
PortletKeys.SO_SITES);
portletPreferences.setValue("defaultSearchTab", searchTab);
portletPreferences.store();
}
private static final String _CLASS_NAME =
"com.liferay.sites.kernel.util.SitesUtil";
private static MethodKey _mergeLayoutSetPrototypeLayoutsMethodKey =
new MethodKey(
ClassResolverUtil.resolveByPortalClassLoader(_CLASS_NAME),
"mergeLayoutSetPrototypeLayouts", Group.class, LayoutSet.class);
private static MethodKey _updateLayoutSetPrototypesMethodKey =
new MethodKey(
ClassResolverUtil.resolveByPortalClassLoader(_CLASS_NAME),
"updateLayoutSetPrototypesLinks", Group.class, long.class,
long.class, boolean.class, boolean.class);
}