001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.sites.action;
016    
017    import com.liferay.portal.DuplicateGroupException;
018    import com.liferay.portal.GroupFriendlyURLException;
019    import com.liferay.portal.GroupInheritContentException;
020    import com.liferay.portal.GroupNameException;
021    import com.liferay.portal.GroupParentException;
022    import com.liferay.portal.LayoutSetVirtualHostException;
023    import com.liferay.portal.LocaleException;
024    import com.liferay.portal.NoSuchGroupException;
025    import com.liferay.portal.NoSuchLayoutException;
026    import com.liferay.portal.PendingBackgroundTaskException;
027    import com.liferay.portal.RemoteExportException;
028    import com.liferay.portal.RemoteOptionsException;
029    import com.liferay.portal.RequiredGroupException;
030    import com.liferay.portal.kernel.dao.orm.QueryUtil;
031    import com.liferay.portal.kernel.exception.PortalException;
032    import com.liferay.portal.kernel.exception.SystemException;
033    import com.liferay.portal.kernel.log.Log;
034    import com.liferay.portal.kernel.log.LogFactoryUtil;
035    import com.liferay.portal.kernel.servlet.MultiSessionMessages;
036    import com.liferay.portal.kernel.servlet.SessionErrors;
037    import com.liferay.portal.kernel.staging.StagingUtil;
038    import com.liferay.portal.kernel.transaction.Propagation;
039    import com.liferay.portal.kernel.util.ArrayUtil;
040    import com.liferay.portal.kernel.util.Constants;
041    import com.liferay.portal.kernel.util.GetterUtil;
042    import com.liferay.portal.kernel.util.HttpUtil;
043    import com.liferay.portal.kernel.util.ListUtil;
044    import com.liferay.portal.kernel.util.ParamUtil;
045    import com.liferay.portal.kernel.util.PrefsPropsUtil;
046    import com.liferay.portal.kernel.util.PropertiesParamUtil;
047    import com.liferay.portal.kernel.util.PropsKeys;
048    import com.liferay.portal.kernel.util.StringPool;
049    import com.liferay.portal.kernel.util.StringUtil;
050    import com.liferay.portal.kernel.util.UnicodeProperties;
051    import com.liferay.portal.liveusers.LiveUsers;
052    import com.liferay.portal.model.Group;
053    import com.liferay.portal.model.GroupConstants;
054    import com.liferay.portal.model.Layout;
055    import com.liferay.portal.model.LayoutConstants;
056    import com.liferay.portal.model.LayoutSet;
057    import com.liferay.portal.model.LayoutSetPrototype;
058    import com.liferay.portal.model.MembershipRequest;
059    import com.liferay.portal.model.MembershipRequestConstants;
060    import com.liferay.portal.model.Role;
061    import com.liferay.portal.model.Team;
062    import com.liferay.portal.security.auth.AuthException;
063    import com.liferay.portal.security.auth.PrincipalException;
064    import com.liferay.portal.security.auth.RemoteAuthException;
065    import com.liferay.portal.service.GroupLocalServiceUtil;
066    import com.liferay.portal.service.GroupServiceUtil;
067    import com.liferay.portal.service.LayoutLocalServiceUtil;
068    import com.liferay.portal.service.LayoutSetLocalServiceUtil;
069    import com.liferay.portal.service.LayoutSetPrototypeServiceUtil;
070    import com.liferay.portal.service.LayoutSetServiceUtil;
071    import com.liferay.portal.service.MembershipRequestLocalServiceUtil;
072    import com.liferay.portal.service.MembershipRequestServiceUtil;
073    import com.liferay.portal.service.RoleLocalServiceUtil;
074    import com.liferay.portal.service.ServiceContext;
075    import com.liferay.portal.service.ServiceContextFactory;
076    import com.liferay.portal.service.ServiceContextThreadLocal;
077    import com.liferay.portal.service.TeamLocalServiceUtil;
078    import com.liferay.portal.spring.transaction.TransactionAttributeBuilder;
079    import com.liferay.portal.spring.transaction.TransactionalCallableUtil;
080    import com.liferay.portal.struts.PortletAction;
081    import com.liferay.portal.theme.ThemeDisplay;
082    import com.liferay.portal.util.PortalUtil;
083    import com.liferay.portal.util.PortletKeys;
084    import com.liferay.portal.util.WebKeys;
085    import com.liferay.portlet.asset.AssetCategoryException;
086    import com.liferay.portlet.asset.AssetTagException;
087    import com.liferay.portlet.sites.util.Sites;
088    import com.liferay.portlet.sites.util.SitesUtil;
089    
090    import java.util.ArrayList;
091    import java.util.List;
092    import java.util.concurrent.Callable;
093    
094    import javax.portlet.ActionRequest;
095    import javax.portlet.ActionResponse;
096    import javax.portlet.PortletConfig;
097    import javax.portlet.PortletRequest;
098    import javax.portlet.PortletURL;
099    import javax.portlet.RenderRequest;
100    import javax.portlet.RenderResponse;
101    
102    import org.apache.struts.action.ActionForm;
103    import org.apache.struts.action.ActionForward;
104    import org.apache.struts.action.ActionMapping;
105    
106    import org.springframework.transaction.interceptor.TransactionAttribute;
107    
108    /**
109     * @author Brian Wing Shun Chan
110     * @author Zsolt Berentey
111     * @author Josef Sustacek
112     */
113    public class EditGroupAction extends PortletAction {
114    
115            @Override
116            public void processAction(
117                            ActionMapping actionMapping, ActionForm actionForm,
118                            PortletConfig portletConfig, ActionRequest actionRequest,
119                            ActionResponse actionResponse)
120                    throws Exception {
121    
122                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
123                            WebKeys.THEME_DISPLAY);
124    
125                    String cmd = ParamUtil.getString(actionRequest, Constants.CMD);
126    
127                    String redirect = ParamUtil.getString(actionRequest, "redirect");
128    
129                    try {
130                            if (cmd.equals(Constants.ADD) || cmd.equals(Constants.UPDATE)) {
131                                    Callable<Group> groupCallable = new GroupCallable(
132                                            actionRequest);
133    
134                                    Group group = TransactionalCallableUtil.call(
135                                            _transactionAttribute, groupCallable);
136    
137                                    if (cmd.equals(Constants.ADD)) {
138                                            themeDisplay.setScopeGroupId(group.getGroupId());
139    
140                                            PortletURL siteAdministrationURL =
141                                                    PortalUtil.getSiteAdministrationURL(
142                                                            actionResponse, themeDisplay,
143                                                            PortletKeys.SITE_SETTINGS);
144    
145                                            String controlPanelURL = HttpUtil.setParameter(
146                                                    themeDisplay.getURLControlPanel(), "p_p_id",
147                                                    PortletKeys.SITES_ADMIN);
148    
149                                            controlPanelURL = HttpUtil.setParameter(
150                                                    controlPanelURL, "controlPanelCategory",
151                                                    themeDisplay.getControlPanelCategory());
152    
153                                            siteAdministrationURL.setParameter(
154                                                    "redirect", controlPanelURL);
155    
156                                            redirect = siteAdministrationURL.toString();
157    
158                                            hideDefaultSuccessMessage(actionRequest);
159    
160                                            MultiSessionMessages.add(
161                                                    actionRequest,
162                                                    PortletKeys.SITE_SETTINGS + "requestProcessed");
163                                    }
164                                    else {
165                                            long newRefererPlid = getRefererPlid(
166                                                    group, themeDisplay.getScopeGroupId(), redirect);
167    
168                                            redirect = HttpUtil.setParameter(
169                                                    redirect, "doAsGroupId", group.getGroupId());
170                                            redirect = HttpUtil.setParameter(
171                                                    redirect, "refererPlid", newRefererPlid);
172                                    }
173                            }
174                            else if (cmd.equals(Constants.DEACTIVATE) ||
175                                             cmd.equals(Constants.RESTORE)) {
176    
177                                    updateActive(actionRequest, cmd);
178                            }
179                            else if (cmd.equals(Constants.DELETE)) {
180                                    deleteGroups(actionRequest);
181                            }
182                            else if (cmd.equals("reset_merge_fail_count_and_merge")) {
183                                    resetMergeFailCountAndMerge(actionRequest);
184                            }
185    
186                            sendRedirect(actionRequest, actionResponse, redirect);
187                    }
188                    catch (Exception e) {
189                            if (e instanceof NoSuchGroupException ||
190                                    e instanceof PrincipalException) {
191    
192                                    SessionErrors.add(actionRequest, e.getClass());
193    
194                                    setForward(actionRequest, "portlet.sites_admin.error");
195                            }
196                            else if (e instanceof AssetCategoryException ||
197                                             e instanceof AssetTagException ||
198                                             e instanceof AuthException ||
199                                             e instanceof DuplicateGroupException ||
200                                             e instanceof GroupFriendlyURLException ||
201                                             e instanceof GroupInheritContentException ||
202                                             e instanceof GroupNameException ||
203                                             e instanceof GroupParentException ||
204                                             e instanceof LayoutSetVirtualHostException ||
205                                             e instanceof LocaleException ||
206                                             e instanceof PendingBackgroundTaskException ||
207                                             e instanceof RemoteAuthException ||
208                                             e instanceof RemoteExportException ||
209                                             e instanceof RemoteOptionsException ||
210                                             e instanceof RequiredGroupException ||
211                                             e instanceof SystemException) {
212    
213                                    if (e instanceof RemoteAuthException) {
214                                            SessionErrors.add(actionRequest, AuthException.class, e);
215                                    }
216                                    else {
217                                            SessionErrors.add(actionRequest, e.getClass(), e);
218                                    }
219                            }
220                            else {
221                                    throw e;
222                            }
223                    }
224                    catch (Throwable t) {
225                            _log.error(t);
226    
227                            setForward(actionRequest, "portlet.sites_admin.error");
228                    }
229            }
230    
231            @Override
232            public ActionForward render(
233                            ActionMapping actionMapping, ActionForm actionForm,
234                            PortletConfig portletConfig, RenderRequest renderRequest,
235                            RenderResponse renderResponse)
236                    throws Exception {
237    
238                    try {
239                            ActionUtil.getGroup(renderRequest);
240                    }
241                    catch (Exception e) {
242                            if (e instanceof NoSuchGroupException ||
243                                    e instanceof PrincipalException) {
244    
245                                    SessionErrors.add(renderRequest, e.getClass());
246    
247                                    return actionMapping.findForward("portlet.sites_admin.error");
248                            }
249                            else {
250                                    throw e;
251                            }
252                    }
253    
254                    return actionMapping.findForward(
255                            getForward(renderRequest, "portlet.sites_admin.edit_site"));
256            }
257    
258            protected void deleteGroups(ActionRequest actionRequest) throws Exception {
259                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
260                            WebKeys.THEME_DISPLAY);
261    
262                    long[] deleteGroupIds = null;
263    
264                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
265    
266                    if (groupId > 0) {
267                            deleteGroupIds = new long[] {groupId};
268                    }
269                    else {
270                            deleteGroupIds = StringUtil.split(
271                                    ParamUtil.getString(actionRequest, "deleteGroupIds"), 0L);
272                    }
273    
274                    for (long deleteGroupId : deleteGroupIds) {
275                            GroupServiceUtil.deleteGroup(deleteGroupId);
276    
277                            LiveUsers.deleteGroup(themeDisplay.getCompanyId(), deleteGroupId);
278                    }
279            }
280    
281            protected String getGroupFriendlyURL(Group liveGroup) {
282                    if (liveGroup != null) {
283                            return liveGroup.getFriendlyURL();
284                    }
285    
286                    return null;
287            }
288    
289            protected Group getLiveGroup(PortletRequest portletRequest)
290                    throws PortalException {
291    
292                    long liveGroupId = ParamUtil.getLong(portletRequest, "liveGroupId");
293    
294                    if (liveGroupId > 0) {
295                            return GroupLocalServiceUtil.getGroup(liveGroupId);
296                    }
297    
298                    return null;
299            }
300    
301            protected long getRefererGroupId(ThemeDisplay themeDisplay)
302                    throws Exception {
303    
304                    long refererGroupId = 0;
305    
306                    try {
307                            Layout refererLayout = LayoutLocalServiceUtil.getLayout(
308                                    themeDisplay.getRefererPlid());
309    
310                            refererGroupId = refererLayout.getGroupId();
311                    }
312                    catch (NoSuchLayoutException nsle) {
313                    }
314    
315                    return refererGroupId;
316            }
317    
318            protected long getRefererPlid(
319                    Group liveGroup, long scopeGroupId, String redirect) {
320    
321                    long refererPlid = GetterUtil.getLong(
322                            HttpUtil.getParameter(redirect, "refererPlid", false));
323    
324                    if ((refererPlid > 0) && liveGroup.hasStagingGroup() &&
325                            (scopeGroupId != liveGroup.getGroupId())) {
326    
327                            Layout firstLayout = LayoutLocalServiceUtil.fetchFirstLayout(
328                                    liveGroup.getGroupId(), false,
329                                    LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
330    
331                            if (firstLayout == null) {
332                                    firstLayout = LayoutLocalServiceUtil.fetchFirstLayout(
333                                            liveGroup.getGroupId(), true,
334                                            LayoutConstants.DEFAULT_PARENT_LAYOUT_ID);
335                            }
336    
337                            if (firstLayout != null) {
338                                    return firstLayout.getPlid();
339                            }
340                    }
341    
342                    return LayoutConstants.DEFAULT_PLID;
343            }
344    
345            protected List<Role> getRoles(PortletRequest portletRequest)
346                    throws Exception {
347    
348                    List<Role> roles = new ArrayList<Role>();
349    
350                    long[] siteRolesRoleIds = StringUtil.split(
351                            ParamUtil.getString(portletRequest, "siteRolesRoleIds"), 0L);
352    
353                    for (long siteRolesRoleId : siteRolesRoleIds) {
354                            if (siteRolesRoleId == 0) {
355                                    continue;
356                            }
357    
358                            Role role = RoleLocalServiceUtil.getRole(siteRolesRoleId);
359    
360                            roles.add(role);
361                    }
362    
363                    return roles;
364            }
365    
366            protected String getStagingGroupFriendlyURL(Group liveGroup) {
367                    if ((liveGroup != null) && liveGroup.hasStagingGroup()) {
368                            Group stagingGroup = liveGroup.getStagingGroup();
369    
370                            return stagingGroup.getFriendlyURL();
371                    }
372    
373                    return null;
374            }
375    
376            protected List<Team> getTeams(PortletRequest portletRequest)
377                    throws Exception {
378    
379                    List<Team> teams = new ArrayList<Team>();
380    
381                    long[] teamsTeamIds = ArrayUtil.unique(
382                            StringUtil.split(
383                                    ParamUtil.getString(portletRequest, "teamsTeamIds"), 0L));
384    
385                    for (long teamsTeamId : teamsTeamIds) {
386                            if (teamsTeamId == 0) {
387                                    continue;
388                            }
389    
390                            Team team = TeamLocalServiceUtil.getTeam(teamsTeamId);
391    
392                            teams.add(team);
393                    }
394    
395                    return teams;
396            }
397    
398            /**
399             * Resets the number of failed merge attempts for the site template, which
400             * is accessed by retrieving the layout set prototype ID. Once the counter
401             * is reset, the modified site template is merged back into its linked site,
402             * which is accessed by retrieving the group ID and private layout set.
403             *
404             * <p>
405             * If the number of failed merge attempts is not equal to zero after the
406             * merge, an error key is submitted to {@link SessionErrors}.
407             * </p>
408             *
409             * @param  actionRequest the portlet request used to retrieve parameters
410             * @throws Exception if an exception occurred
411             */
412            protected void resetMergeFailCountAndMerge(ActionRequest actionRequest)
413                    throws Exception {
414    
415                    long layoutSetPrototypeId = ParamUtil.getLong(
416                            actionRequest, "layoutSetPrototypeId");
417    
418                    LayoutSetPrototype layoutSetPrototype =
419                            LayoutSetPrototypeServiceUtil.getLayoutSetPrototype(
420                                    layoutSetPrototypeId);
421    
422                    SitesUtil.setMergeFailCount(layoutSetPrototype, 0);
423    
424                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
425                    boolean privateLayoutSet = ParamUtil.getBoolean(
426                            actionRequest, "privateLayoutSet");
427    
428                    LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
429                            groupId, privateLayoutSet);
430    
431                    SitesUtil.resetPrototype(layoutSet);
432    
433                    Group group = GroupLocalServiceUtil.getGroup(groupId);
434    
435                    SitesUtil.mergeLayoutSetPrototypeLayouts(group, layoutSet);
436    
437                    layoutSetPrototype =
438                            LayoutSetPrototypeServiceUtil.getLayoutSetPrototype(
439                                    layoutSetPrototypeId);
440    
441                    if (SitesUtil.getMergeFailCount(layoutSetPrototype) > 0) {
442                            SessionErrors.add(actionRequest, "resetMergeFailCountAndMerge");
443                    }
444            }
445    
446            protected void updateActive(ActionRequest actionRequest, String cmd)
447                    throws Exception {
448    
449                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
450                            WebKeys.THEME_DISPLAY);
451    
452                    long groupId = ParamUtil.getLong(actionRequest, "groupId");
453    
454                    if ((groupId == themeDisplay.getDoAsGroupId()) ||
455                            (groupId == themeDisplay.getScopeGroupId()) ||
456                            (groupId == getRefererGroupId(themeDisplay))) {
457    
458                            throw new RequiredGroupException(
459                                    String.valueOf(groupId), RequiredGroupException.CURRENT_GROUP);
460                    }
461    
462                    Group group = GroupServiceUtil.getGroup(groupId);
463    
464                    boolean active = false;
465    
466                    if (cmd.equals(Constants.RESTORE)) {
467                            active = true;
468                    }
469    
470                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
471                            Group.class.getName(), actionRequest);
472    
473                    GroupServiceUtil.updateGroup(
474                            groupId, group.getParentGroupId(), group.getName(),
475                            group.getDescription(), group.getType(), group.isManualMembership(),
476                            group.getMembershipRestriction(), group.getFriendlyURL(),
477                            group.isInheritContent(), active, serviceContext);
478            }
479    
480            protected Group updateGroup(ActionRequest actionRequest) throws Exception {
481                    ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
482                            WebKeys.THEME_DISPLAY);
483    
484                    long userId = PortalUtil.getUserId(actionRequest);
485    
486                    long liveGroupId = ParamUtil.getLong(actionRequest, "liveGroupId");
487    
488                    long parentGroupId = ParamUtil.getLong(
489                            actionRequest, "parentGroupSearchContainerPrimaryKeys",
490                            GroupConstants.DEFAULT_PARENT_GROUP_ID);
491                    String name = null;
492                    String description = null;
493                    int type = 0;
494                    String friendlyURL = null;
495                    boolean inheritContent = false;
496                    boolean active = false;
497                    boolean manualMembership = true;
498    
499                    int membershipRestriction =
500                            GroupConstants.DEFAULT_MEMBERSHIP_RESTRICTION;
501    
502                    boolean actionRequestMembershipRestriction = ParamUtil.getBoolean(
503                            actionRequest, "membershipRestriction");
504    
505                    if (actionRequestMembershipRestriction &&
506                            (parentGroupId != GroupConstants.DEFAULT_PARENT_GROUP_ID)) {
507    
508                            membershipRestriction =
509                                    GroupConstants.MEMBERSHIP_RESTRICTION_TO_PARENT_SITE_MEMBERS;
510                    }
511    
512                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
513                            Group.class.getName(), actionRequest);
514    
515                    ServiceContextThreadLocal.pushServiceContext(serviceContext);
516    
517                    Group liveGroup = null;
518    
519                    if (liveGroupId <= 0) {
520    
521                            // Add group
522    
523                            name = ParamUtil.getString(actionRequest, "name");
524                            description = ParamUtil.getString(actionRequest, "description");
525                            type = ParamUtil.getInteger(actionRequest, "type");
526                            friendlyURL = ParamUtil.getString(actionRequest, "friendlyURL");
527                            manualMembership = ParamUtil.getBoolean(
528                                    actionRequest, "manualMembership");
529                            inheritContent = ParamUtil.getBoolean(
530                                    actionRequest, "inheritContent");
531                            active = ParamUtil.getBoolean(actionRequest, "active");
532    
533                            liveGroup = GroupServiceUtil.addGroup(
534                                    parentGroupId, GroupConstants.DEFAULT_LIVE_GROUP_ID, name,
535                                    description, type, manualMembership, membershipRestriction,
536                                    friendlyURL, true, inheritContent, active, serviceContext);
537    
538                            LiveUsers.joinGroup(
539                                    themeDisplay.getCompanyId(), liveGroup.getGroupId(), userId);
540                    }
541                    else {
542    
543                            // Update group
544    
545                            liveGroup = GroupLocalServiceUtil.getGroup(liveGroupId);
546    
547                            name = ParamUtil.getString(
548                                    actionRequest, "name", liveGroup.getName());
549                            description = ParamUtil.getString(
550                                    actionRequest, "description", liveGroup.getDescription());
551                            type = ParamUtil.getInteger(
552                                    actionRequest, "type", liveGroup.getType());
553                            manualMembership = ParamUtil.getBoolean(
554                                    actionRequest, "manualMembership",
555                                    liveGroup.isManualMembership());
556                            friendlyURL = ParamUtil.getString(
557                                    actionRequest, "friendlyURL", liveGroup.getFriendlyURL());
558                            inheritContent = ParamUtil.getBoolean(
559                                    actionRequest, "inheritContent", liveGroup.getInheritContent());
560                            active = ParamUtil.getBoolean(
561                                    actionRequest, "active", liveGroup.getActive());
562    
563                            liveGroup = GroupServiceUtil.updateGroup(
564                                    liveGroupId, parentGroupId, name, description, type,
565                                    manualMembership, membershipRestriction, friendlyURL,
566                                    inheritContent, active, serviceContext);
567    
568                            if (type == GroupConstants.TYPE_SITE_OPEN) {
569                                    List<MembershipRequest> membershipRequests =
570                                            MembershipRequestLocalServiceUtil.search(
571                                                    liveGroupId, MembershipRequestConstants.STATUS_PENDING,
572                                                    QueryUtil.ALL_POS, QueryUtil.ALL_POS);
573    
574                                    for (MembershipRequest membershipRequest : membershipRequests) {
575                                            MembershipRequestServiceUtil.updateStatus(
576                                                    membershipRequest.getMembershipRequestId(),
577                                                    themeDisplay.translate(
578                                                            "your-membership-has-been-approved"),
579                                                    MembershipRequestConstants.STATUS_APPROVED,
580                                                    serviceContext);
581    
582                                            LiveUsers.joinGroup(
583                                                    themeDisplay.getCompanyId(),
584                                                    membershipRequest.getGroupId(),
585                                                    new long[] {membershipRequest.getUserId()});
586                                    }
587                            }
588                    }
589    
590                    // Settings
591    
592                    UnicodeProperties typeSettingsProperties =
593                            liveGroup.getTypeSettingsProperties();
594    
595                    String customJspServletContextName = ParamUtil.getString(
596                            actionRequest, "customJspServletContextName",
597                            typeSettingsProperties.getProperty("customJspServletContextName"));
598    
599                    typeSettingsProperties.setProperty(
600                            "customJspServletContextName", customJspServletContextName);
601    
602                    typeSettingsProperties.setProperty(
603                            "defaultSiteRoleIds",
604                            ListUtil.toString(
605                                    getRoles(actionRequest), Role.ROLE_ID_ACCESSOR,
606                                    StringPool.COMMA));
607                    typeSettingsProperties.setProperty(
608                            "defaultTeamIds",
609                            ListUtil.toString(
610                                    getTeams(actionRequest), Team.TEAM_ID_ACCESSOR,
611                                    StringPool.COMMA));
612    
613                    String[] analyticsTypes = PrefsPropsUtil.getStringArray(
614                            themeDisplay.getCompanyId(), PropsKeys.ADMIN_ANALYTICS_TYPES,
615                            StringPool.NEW_LINE);
616    
617                    for (String analyticsType : analyticsTypes) {
618                            if (StringUtil.equalsIgnoreCase(analyticsType, "google")) {
619                                    String googleAnalyticsId = ParamUtil.getString(
620                                            actionRequest, "googleAnalyticsId",
621                                            typeSettingsProperties.getProperty("googleAnalyticsId"));
622    
623                                    typeSettingsProperties.setProperty(
624                                            "googleAnalyticsId", googleAnalyticsId);
625                            }
626                            else {
627                                    String analyticsScript = ParamUtil.getString(
628                                            actionRequest, Sites.ANALYTICS_PREFIX + analyticsType,
629                                            typeSettingsProperties.getProperty(analyticsType));
630    
631                                    typeSettingsProperties.setProperty(
632                                            Sites.ANALYTICS_PREFIX + analyticsType, analyticsScript);
633                            }
634                    }
635    
636                    String publicRobots = ParamUtil.getString(
637                            actionRequest, "publicRobots",
638                            liveGroup.getTypeSettingsProperty("false-robots.txt"));
639                    String privateRobots = ParamUtil.getString(
640                            actionRequest, "privateRobots",
641                            liveGroup.getTypeSettingsProperty("true-robots.txt"));
642    
643                    typeSettingsProperties.setProperty("false-robots.txt", publicRobots);
644                    typeSettingsProperties.setProperty("true-robots.txt", privateRobots);
645    
646                    boolean trashEnabled = ParamUtil.getBoolean(
647                            actionRequest, "trashEnabled",
648                            GetterUtil.getBoolean(
649                                    typeSettingsProperties.getProperty("trashEnabled"), true));
650    
651                    typeSettingsProperties.setProperty(
652                            "trashEnabled", String.valueOf(trashEnabled));
653    
654                    int trashEntriesMaxAgeCompany = PrefsPropsUtil.getInteger(
655                            themeDisplay.getCompanyId(), PropsKeys.TRASH_ENTRIES_MAX_AGE);
656    
657                    double trashEntriesMaxAgeGroup = ParamUtil.getDouble(
658                            actionRequest, "trashEntriesMaxAge");
659    
660                    if (trashEntriesMaxAgeGroup > 0) {
661                            trashEntriesMaxAgeGroup *= 1440;
662                    }
663                    else {
664                            trashEntriesMaxAgeGroup = GetterUtil.getInteger(
665                                    typeSettingsProperties.getProperty("trashEntriesMaxAge"),
666                                    trashEntriesMaxAgeCompany);
667                    }
668    
669                    if (trashEntriesMaxAgeGroup != trashEntriesMaxAgeCompany) {
670                            typeSettingsProperties.setProperty(
671                                    "trashEntriesMaxAge",
672                                    String.valueOf(GetterUtil.getInteger(trashEntriesMaxAgeGroup)));
673                    }
674                    else {
675                            typeSettingsProperties.remove("trashEntriesMaxAge");
676                    }
677    
678                    int contentSharingWithChildrenEnabled = ParamUtil.getInteger(
679                            actionRequest, "contentSharingWithChildrenEnabled",
680                            GetterUtil.getInteger(
681                                    typeSettingsProperties.getProperty(
682                                            "contentSharingWithChildrenEnabled"),
683                                    Sites.CONTENT_SHARING_WITH_CHILDREN_DEFAULT_VALUE));
684    
685                    typeSettingsProperties.setProperty(
686                            "contentSharingWithChildrenEnabled",
687                            String.valueOf(contentSharingWithChildrenEnabled));
688    
689                    UnicodeProperties formTypeSettingsProperties =
690                            PropertiesParamUtil.getProperties(
691                                    actionRequest, "TypeSettingsProperties--");
692    
693                    typeSettingsProperties.putAll(formTypeSettingsProperties);
694    
695                    // Virtual hosts
696    
697                    LayoutSet publicLayoutSet = liveGroup.getPublicLayoutSet();
698    
699                    String publicVirtualHost = ParamUtil.getString(
700                            actionRequest, "publicVirtualHost",
701                            publicLayoutSet.getVirtualHostname());
702    
703                    LayoutSetServiceUtil.updateVirtualHost(
704                            liveGroup.getGroupId(), false, publicVirtualHost);
705    
706                    LayoutSet privateLayoutSet = liveGroup.getPrivateLayoutSet();
707    
708                    String privateVirtualHost = ParamUtil.getString(
709                            actionRequest, "privateVirtualHost",
710                            privateLayoutSet.getVirtualHostname());
711    
712                    LayoutSetServiceUtil.updateVirtualHost(
713                            liveGroup.getGroupId(), true, privateVirtualHost);
714    
715                    // Staging
716    
717                    if (liveGroup.hasStagingGroup()) {
718                            Group stagingGroup = liveGroup.getStagingGroup();
719    
720                            friendlyURL = ParamUtil.getString(
721                                    actionRequest, "stagingFriendlyURL",
722                                    stagingGroup.getFriendlyURL());
723    
724                            GroupServiceUtil.updateFriendlyURL(
725                                    stagingGroup.getGroupId(), friendlyURL);
726    
727                            LayoutSet stagingPublicLayoutSet =
728                                    stagingGroup.getPublicLayoutSet();
729    
730                            publicVirtualHost = ParamUtil.getString(
731                                    actionRequest, "stagingPublicVirtualHost",
732                                    stagingPublicLayoutSet.getVirtualHostname());
733    
734                            LayoutSetServiceUtil.updateVirtualHost(
735                                    stagingGroup.getGroupId(), false, publicVirtualHost);
736    
737                            LayoutSet stagingPrivateLayoutSet =
738                                    stagingGroup.getPrivateLayoutSet();
739    
740                            privateVirtualHost = ParamUtil.getString(
741                                    actionRequest, "stagingPrivateVirtualHost",
742                                    stagingPrivateLayoutSet.getVirtualHostname());
743    
744                            LayoutSetServiceUtil.updateVirtualHost(
745                                    stagingGroup.getGroupId(), true, privateVirtualHost);
746    
747                            GroupServiceUtil.updateGroup(
748                                    stagingGroup.getGroupId(), typeSettingsProperties.toString());
749                    }
750    
751                    liveGroup = GroupServiceUtil.updateGroup(
752                            liveGroup.getGroupId(), typeSettingsProperties.toString());
753    
754                    // Layout set prototypes
755    
756                    long privateLayoutSetPrototypeId = ParamUtil.getLong(
757                            actionRequest, "privateLayoutSetPrototypeId");
758                    long publicLayoutSetPrototypeId = ParamUtil.getLong(
759                            actionRequest, "publicLayoutSetPrototypeId");
760    
761                    boolean privateLayoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
762                            actionRequest, "privateLayoutSetPrototypeLinkEnabled",
763                            privateLayoutSet.isLayoutSetPrototypeLinkEnabled());
764                    boolean publicLayoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
765                            actionRequest, "publicLayoutSetPrototypeLinkEnabled",
766                            publicLayoutSet.isLayoutSetPrototypeLinkEnabled());
767    
768                    if ((privateLayoutSetPrototypeId == 0) &&
769                            (publicLayoutSetPrototypeId == 0) &&
770                            !privateLayoutSetPrototypeLinkEnabled &&
771                            !publicLayoutSetPrototypeLinkEnabled) {
772    
773                            long layoutSetPrototypeId = ParamUtil.getLong(
774                                    actionRequest, "layoutSetPrototypeId");
775                            int layoutSetVisibility = ParamUtil.getInteger(
776                                    actionRequest, "layoutSetVisibility");
777                            boolean layoutSetPrototypeLinkEnabled = ParamUtil.getBoolean(
778                                    actionRequest, "layoutSetPrototypeLinkEnabled",
779                                    (layoutSetPrototypeId > 0));
780    
781                            if (layoutSetVisibility == _LAYOUT_SET_VISIBILITY_PRIVATE) {
782                                    privateLayoutSetPrototypeId = layoutSetPrototypeId;
783    
784                                    privateLayoutSetPrototypeLinkEnabled =
785                                            layoutSetPrototypeLinkEnabled;
786                            }
787                            else {
788                                    publicLayoutSetPrototypeId = layoutSetPrototypeId;
789    
790                                    publicLayoutSetPrototypeLinkEnabled =
791                                            layoutSetPrototypeLinkEnabled;
792                            }
793                    }
794    
795                    if (!liveGroup.isStaged() || liveGroup.isStagedRemotely()) {
796                            SitesUtil.updateLayoutSetPrototypesLinks(
797                                    liveGroup, publicLayoutSetPrototypeId,
798                                    privateLayoutSetPrototypeId,
799                                    publicLayoutSetPrototypeLinkEnabled,
800                                    privateLayoutSetPrototypeLinkEnabled);
801                    }
802                    else {
803                            SitesUtil.updateLayoutSetPrototypesLinks(
804                                    liveGroup.getStagingGroup(), publicLayoutSetPrototypeId,
805                                    privateLayoutSetPrototypeId,
806                                    publicLayoutSetPrototypeLinkEnabled,
807                                    privateLayoutSetPrototypeLinkEnabled);
808                    }
809    
810                    // Staging
811    
812                    if (!privateLayoutSet.isLayoutSetPrototypeLinkActive() &&
813                            !publicLayoutSet.isLayoutSetPrototypeLinkActive()) {
814    
815                            StagingUtil.updateStaging(actionRequest, liveGroup);
816                    }
817    
818                    return liveGroup;
819            }
820    
821            private static final int _LAYOUT_SET_VISIBILITY_PRIVATE = 1;
822    
823            private static Log _log = LogFactoryUtil.getLog(EditGroupAction.class);
824    
825            private TransactionAttribute _transactionAttribute =
826                    TransactionAttributeBuilder.build(
827                            Propagation.REQUIRED, new Class<?>[]{Exception.class});
828    
829            private class GroupCallable implements Callable<Group> {
830    
831                    @Override
832                    public Group call() throws Exception {
833                            return updateGroup(_actionRequest);
834                    }
835    
836                    private GroupCallable(ActionRequest actionRequest) {
837                            _actionRequest = actionRequest;
838                    }
839    
840                    private ActionRequest _actionRequest;
841    
842            }
843    
844    }