001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portlet.sites.util;
016    
017    import com.liferay.portal.events.EventsProcessorUtil;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.exception.SystemException;
020    import com.liferay.portal.kernel.language.LanguageUtil;
021    import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
022    import com.liferay.portal.kernel.lar.UserIdStrategy;
023    import com.liferay.portal.kernel.util.GetterUtil;
024    import com.liferay.portal.kernel.util.ParamUtil;
025    import com.liferay.portal.kernel.util.PropsKeys;
026    import com.liferay.portal.kernel.util.Validator;
027    import com.liferay.portal.model.Group;
028    import com.liferay.portal.model.Layout;
029    import com.liferay.portal.model.LayoutSet;
030    import com.liferay.portal.model.LayoutSetPrototype;
031    import com.liferay.portal.model.LayoutTypePortlet;
032    import com.liferay.portal.model.impl.LayoutTypePortletImpl;
033    import com.liferay.portal.security.auth.PrincipalException;
034    import com.liferay.portal.security.permission.ActionKeys;
035    import com.liferay.portal.security.permission.PermissionChecker;
036    import com.liferay.portal.service.GroupServiceUtil;
037    import com.liferay.portal.service.LayoutLocalServiceUtil;
038    import com.liferay.portal.service.LayoutServiceUtil;
039    import com.liferay.portal.service.LayoutSetLocalServiceUtil;
040    import com.liferay.portal.service.LayoutSetPrototypeLocalServiceUtil;
041    import com.liferay.portal.service.ServiceContext;
042    import com.liferay.portal.service.ServiceContextFactory;
043    import com.liferay.portal.service.permission.GroupPermissionUtil;
044    import com.liferay.portal.service.permission.LayoutPermissionUtil;
045    import com.liferay.portal.theme.PortletDisplay;
046    import com.liferay.portal.theme.ThemeDisplay;
047    import com.liferay.portal.util.LayoutSettings;
048    import com.liferay.portal.util.PortalUtil;
049    import com.liferay.portal.util.PortletKeys;
050    import com.liferay.portal.util.WebKeys;
051    
052    import java.io.File;
053    import java.io.InputStream;
054    
055    import java.util.Date;
056    import java.util.LinkedHashMap;
057    import java.util.List;
058    import java.util.Locale;
059    import java.util.Map;
060    
061    import javax.portlet.ActionRequest;
062    import javax.portlet.ActionResponse;
063    import javax.portlet.PortletURL;
064    import javax.portlet.RenderRequest;
065    import javax.portlet.RenderResponse;
066    
067    import javax.servlet.http.HttpServletRequest;
068    import javax.servlet.http.HttpServletResponse;
069    
070    /**
071     * @author Raymond Augé
072     * @author Ryan Park
073     * @author Zsolt Berentey
074     */
075    public class SitesUtil {
076    
077            public static void addPortletBreadcrumbEntries(
078                            Group group, String pagesName, PortletURL redirectURL,
079                            HttpServletRequest request, RenderResponse renderResponse)
080                    throws Exception {
081    
082                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
083                            com.liferay.portal.kernel.util.WebKeys.THEME_DISPLAY);
084    
085                    PortletDisplay portletDisplay = themeDisplay.getPortletDisplay();
086    
087                    String portletName = portletDisplay.getPortletName();
088    
089                    if ((renderResponse == null) ||
090                            portletName.equals(PortletKeys.GROUP_PAGES) ||
091                            portletName.equals(PortletKeys.MY_PAGES)) {
092    
093                            return;
094                    }
095    
096                    Locale locale = themeDisplay.getLocale();
097    
098                    if (group.isLayoutPrototype()) {
099                            PortalUtil.addPortletBreadcrumbEntry(
100                                    request, LanguageUtil.get(locale, "page-template"), null);
101    
102                            PortalUtil.addPortletBreadcrumbEntry(
103                                    request, group.getDescriptiveName(), redirectURL.toString());
104                    }
105                    else {
106                            PortalUtil.addPortletBreadcrumbEntry(
107                                    request, group.getDescriptiveName(), null);
108                    }
109    
110                    if (!group.isLayoutPrototype()) {
111                            PortalUtil.addPortletBreadcrumbEntry(
112                                    request, LanguageUtil.get(locale, pagesName),
113                                    redirectURL.toString());
114                    }
115            }
116    
117            public static void applyLayoutSetPrototypes(
118                            Group group, long publicLayoutSetPrototypeId,
119                            long privateLayoutSetPrototypeId, ServiceContext serviceContext)
120                    throws Exception {
121    
122                    Group sourceGroup = null;
123    
124                    if (publicLayoutSetPrototypeId > 0) {
125                            LayoutSetPrototype layoutSetPrototype =
126                                    LayoutSetPrototypeLocalServiceUtil.getLayoutSetPrototype(
127                                            publicLayoutSetPrototypeId);
128    
129                            LayoutSet publicLayoutSet = group.getPublicLayoutSet();
130    
131                            copyLayoutSet(
132                                    layoutSetPrototype.getLayoutSet(), publicLayoutSet,
133                                    serviceContext);
134    
135                            sourceGroup = layoutSetPrototype.getGroup();
136                    }
137    
138                    if (privateLayoutSetPrototypeId > 0) {
139                            LayoutSetPrototype layoutSetPrototype =
140                                    LayoutSetPrototypeLocalServiceUtil.getLayoutSetPrototype(
141                                            privateLayoutSetPrototypeId);
142    
143                            LayoutSet privateLayoutSet = group.getPrivateLayoutSet();
144    
145                            copyLayoutSet(
146                                    layoutSetPrototype.getLayoutSet(), privateLayoutSet,
147                                    serviceContext);
148    
149                            if (sourceGroup == null) {
150                                    sourceGroup = layoutSetPrototype.getGroup();
151                            }
152                    }
153    
154                    if (sourceGroup != null) {
155                            copyTypeSettings(sourceGroup, group);
156                    }
157            }
158    
159            public static void copyLayout(
160                            long userId, Layout sourceLayout, Layout targetLayout,
161                            ServiceContext serviceContext)
162                    throws Exception {
163    
164                    Map<String, String[]> parameterMap =
165                            getLayoutSetPrototypeParameters(serviceContext);
166    
167                    parameterMap.put(
168                            PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
169                            new String[] {Boolean.FALSE.toString()});
170    
171                    File file = LayoutLocalServiceUtil.exportLayoutsAsFile(
172                            sourceLayout.getGroupId(), sourceLayout.isPrivateLayout(),
173                            new long[] {sourceLayout.getLayoutId()}, parameterMap, null, null);
174    
175                    try {
176                            LayoutLocalServiceUtil.importLayouts(
177                                    userId, targetLayout.getGroupId(),
178                                    targetLayout.isPrivateLayout(), parameterMap, file);
179                    }
180                    finally {
181                            file.delete();
182                    }
183            }
184    
185            public static void copyLayoutSet(
186                            LayoutSet sourceLayoutSet, LayoutSet targetLayoutSet,
187                            ServiceContext serviceContext)
188                    throws Exception {
189    
190                    Map<String, String[]> parameterMap = getLayoutSetPrototypeParameters(
191                            serviceContext);
192    
193                    if (!targetLayoutSet.isPrivateLayout()) {
194                            parameterMap.put(
195                                    PortletDataHandlerKeys.PUBLIC_LAYOUT_PERMISSIONS,
196                                    new String[] {Boolean.TRUE.toString()});
197                    }
198    
199                    File file = LayoutLocalServiceUtil.exportLayoutsAsFile(
200                            sourceLayoutSet.getGroupId(), sourceLayoutSet.isPrivateLayout(),
201                            null, parameterMap, null, null);
202    
203                    try {
204                            LayoutServiceUtil.importLayouts(
205                                    targetLayoutSet.getGroupId(), targetLayoutSet.isPrivateLayout(),
206                                    parameterMap, file);
207                    }
208                    finally {
209                            file.delete();
210                    }
211            }
212    
213            public static void copyTypeSettings(Group sourceGroup, Group targetGroup)
214                    throws Exception {
215    
216                    GroupServiceUtil.updateGroup(
217                            targetGroup.getGroupId(), sourceGroup.getTypeSettings());
218            }
219    
220            public static Object[] deleteLayout(
221                            ActionRequest actionRequest, ActionResponse actionResponse)
222                    throws Exception {
223    
224                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
225                            actionRequest);
226                    HttpServletResponse response = PortalUtil.getHttpServletResponse(
227                            actionResponse);
228    
229                    return deleteLayout(request, response);
230            }
231    
232            public static Object[] deleteLayout(
233                            HttpServletRequest request, HttpServletResponse response)
234                    throws Exception {
235    
236                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
237                            WebKeys.THEME_DISPLAY);
238    
239                    PermissionChecker permissionChecker =
240                            themeDisplay.getPermissionChecker();
241    
242                    long plid = ParamUtil.getLong(request, "plid");
243    
244                    long groupId = ParamUtil.getLong(request, "groupId");
245                    boolean privateLayout = ParamUtil.getBoolean(request, "privateLayout");
246                    long layoutId = ParamUtil.getLong(request, "layoutId");
247    
248                    Layout layout = null;
249    
250                    if (plid <= 0) {
251                            layout = LayoutLocalServiceUtil.getLayout(
252                                    groupId, privateLayout, layoutId);
253                    }
254                    else {
255                            layout = LayoutLocalServiceUtil.getLayout(plid);
256    
257                            groupId = layout.getGroupId();
258                            privateLayout = layout.isPrivateLayout();
259                            layoutId = layout.getLayoutId();
260                    }
261    
262                    Group group = layout.getGroup();
263                    String oldFriendlyURL = layout.getFriendlyURL();
264    
265                    if (group.isStagingGroup() &&
266                            !GroupPermissionUtil.contains(
267                                    permissionChecker, groupId, ActionKeys.MANAGE_STAGING) &&
268                            !GroupPermissionUtil.contains(
269                                    permissionChecker, groupId, ActionKeys.PUBLISH_STAGING)) {
270    
271                            throw new PrincipalException();
272                    }
273    
274                    if (LayoutPermissionUtil.contains(
275                                    permissionChecker, layout, ActionKeys.DELETE)) {
276    
277                            LayoutSettings layoutSettings = LayoutSettings.getInstance(layout);
278    
279                            EventsProcessorUtil.process(
280                                    PropsKeys.LAYOUT_CONFIGURATION_ACTION_DELETE,
281                                    layoutSettings.getConfigurationActionDelete(), request,
282                                    response);
283                    }
284    
285                    LayoutSet layoutSet = layout.getLayoutSet();
286    
287                    Group layoutSetGroup = layoutSet.getGroup();
288    
289                    ServiceContext serviceContext = ServiceContextFactory.getInstance(
290                            request);
291    
292                    if (layoutSetGroup.isLayoutSetPrototype()) {
293                            LayoutSetPrototype layoutSetPrototype =
294                                    LayoutSetPrototypeLocalServiceUtil.getLayoutSetPrototype(
295                                            layoutSetGroup.getClassPK());
296    
297                            List<LayoutSet> linkedLayoutSets =
298                                    LayoutSetLocalServiceUtil.getLayoutSetsByLayoutSetPrototypeUuid(
299                                            layoutSetPrototype.getUuid());
300    
301                            for (LayoutSet linkedLayoutSet : linkedLayoutSets) {
302                                    Layout linkedLayout =
303                                            LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
304                                                    layout.getUuid(), linkedLayoutSet.getGroupId());
305    
306                                    if ((linkedLayout != null) &&
307                                            (isLayoutLocked(linkedLayout) ||
308                                             isLayoutToBeUpdatedFromTemplate(linkedLayout))) {
309    
310                                            LayoutServiceUtil.deleteLayout(
311                                                    linkedLayout.getPlid(), serviceContext);
312                                    }
313                            }
314                    }
315    
316                    LayoutServiceUtil.deleteLayout(
317                            groupId, privateLayout, layoutId, serviceContext);
318    
319                    return new Object[] {group, oldFriendlyURL};
320            }
321    
322            public static void deleteLayout(
323                            RenderRequest renderRequest, RenderResponse renderResponse)
324                    throws Exception {
325    
326                    HttpServletRequest request = PortalUtil.getHttpServletRequest(
327                            renderRequest);
328                    HttpServletResponse response = PortalUtil.getHttpServletResponse(
329                            renderResponse);
330    
331                    deleteLayout(request, response);
332            }
333    
334            public static File exportLayoutSetPrototype(
335                            LayoutSetPrototype layoutSetPrototype,
336                            ServiceContext serviceContext)
337                    throws PortalException, SystemException {
338    
339                    LayoutSet layoutSet = layoutSetPrototype.getLayoutSet();
340    
341                    Map<String, String[]> parameterMap = getLayoutSetPrototypeParameters(
342                            serviceContext);
343    
344                    return LayoutLocalServiceUtil.exportLayoutsAsFile(
345                            layoutSet.getGroupId(), layoutSet.isPrivateLayout(),
346                            null, parameterMap, null, null);
347            }
348    
349            public static Map<String, String[]> getLayoutSetPrototypeParameters(
350                    ServiceContext serviceContext) {
351    
352                    Map<String, String[]> parameterMap =
353                            new LinkedHashMap<String, String[]>();
354    
355                    parameterMap.put(
356                            PortletDataHandlerKeys.CATEGORIES,
357                            new String[] {Boolean.TRUE.toString()});
358                    parameterMap.put(
359                            PortletDataHandlerKeys.DATA_STRATEGY,
360                            new String[] {PortletDataHandlerKeys.DATA_STRATEGY_MIRROR});
361                    parameterMap.put(
362                            PortletDataHandlerKeys.DELETE_MISSING_LAYOUTS,
363                            new String[] {Boolean.TRUE.toString()});
364                    parameterMap.put(
365                            PortletDataHandlerKeys.DELETE_PORTLET_DATA,
366                            new String[] {Boolean.FALSE.toString()});
367    
368                    String siteTemplateRelationship = ParamUtil.getString(
369                            serviceContext, "siteTemplateRelationship");
370    
371                    if (siteTemplateRelationship.equals("inherited")) {
372                            parameterMap.put(
373                                    PortletDataHandlerKeys.LAYOUT_SET_PROTOTYPE_INHERITED,
374                                    new String[] {Boolean.TRUE.toString()});
375                    }
376    
377                    parameterMap.put(
378                            PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
379                            new String[] {
380                                    PortletDataHandlerKeys.
381                                            LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE
382                            });
383                    parameterMap.put(
384                            PortletDataHandlerKeys.PERFORM_DIRECT_BINARY_IMPORT,
385                            new String[] {Boolean.TRUE.toString()});
386                    parameterMap.put(
387                            PortletDataHandlerKeys.PERMISSIONS,
388                            new String[] {Boolean.TRUE.toString()});
389                    parameterMap.put(
390                            PortletDataHandlerKeys.PORTLET_DATA,
391                            new String[] {Boolean.TRUE.toString()});
392                    parameterMap.put(
393                            PortletDataHandlerKeys.PORTLET_DATA_ALL,
394                            new String[] {Boolean.TRUE.toString()});
395                    parameterMap.put(
396                            PortletDataHandlerKeys.PORTLET_SETUP,
397                            new String[] {Boolean.TRUE.toString()});
398                    parameterMap.put(
399                            PortletDataHandlerKeys.PORTLET_USER_PREFERENCES,
400                            new String[] {Boolean.TRUE.toString()});
401                    parameterMap.put(
402                            PortletDataHandlerKeys.THEME,
403                            new String[] {Boolean.FALSE.toString()});
404                    parameterMap.put(
405                            PortletDataHandlerKeys.THEME_REFERENCE,
406                            new String[] {Boolean.TRUE.toString()});
407                    parameterMap.put(
408                            PortletDataHandlerKeys.USER_ID_STRATEGY,
409                            new String[] {UserIdStrategy.CURRENT_USER_ID});
410                    parameterMap.put(
411                            PortletDataHandlerKeys.USER_PERMISSIONS,
412                            new String[] {Boolean.FALSE.toString()});
413    
414                    return parameterMap;
415            }
416    
417            public static void importLayoutSetPrototype(
418                            LayoutSetPrototype layoutSetPrototype, InputStream inputStream,
419                            ServiceContext serviceContext)
420                    throws PortalException, SystemException {
421    
422                    LayoutSet layoutSet = layoutSetPrototype.getLayoutSet();
423    
424                    Map<String, String[]> parameterMap = getLayoutSetPrototypeParameters(
425                            serviceContext);
426    
427                    LayoutServiceUtil.importLayouts(
428                            layoutSet.getGroupId(), layoutSet.isPrivateLayout(),
429                            parameterMap, inputStream);
430            }
431    
432            public static boolean isLayoutLocked(Layout layout) {
433                    try {
434                            LayoutSet layoutSet = layout.getLayoutSet();
435    
436                            if (layout.isLayoutPrototypeLinkEnabled() ||
437                                    layoutSet.isLayoutSetPrototypeLinkEnabled()) {
438    
439                                    LayoutTypePortletImpl layoutTypePortlet =
440                                            new LayoutTypePortletImpl(layout);
441    
442                                    return isLayoutLocked(layoutTypePortlet);
443                            }
444                    }
445                    catch (Exception e) {
446                    }
447    
448                    return false;
449            }
450    
451            public static boolean isLayoutLocked(
452                    LayoutTypePortlet layoutTypePortlet) {
453    
454                    Layout layout = layoutTypePortlet.getLayout();
455    
456                    try {
457                            LayoutSet layoutSet = layout.getLayoutSet();
458    
459                            if (layout.isLayoutPrototypeLinkEnabled() ||
460                                    layoutSet.isLayoutSetPrototypeLinkEnabled()) {
461    
462                                    String locked = layoutTypePortlet.getTemplateProperty("locked");
463    
464                                    if (Validator.isNotNull(locked)) {
465                                            return GetterUtil.getBoolean(locked);
466                                    }
467                                    else if (Validator.isNotNull(layout.getTemplateLayoutUuid())) {
468                                            return isLayoutSetLocked(layoutSet);
469                                    }
470                            }
471                    }
472                    catch (Exception e) {
473                    }
474    
475                    return false;
476            }
477    
478            public static boolean isLayoutSetLocked(
479                    Group group, boolean privateLayout) {
480    
481                    try {
482                            LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
483                                    group.getGroupId(), privateLayout);
484    
485                            return isLayoutSetLocked(layoutSet);
486                    }
487                    catch (Exception e) {
488                    }
489    
490                    return true;
491            }
492    
493            public static boolean isLayoutSetLocked(LayoutSet layoutSet) {
494                    if (layoutSet.isLayoutSetPrototypeLinkEnabled()) {
495                            try {
496                                    LayoutSetPrototype layoutSetPrototype =
497                                            LayoutSetPrototypeLocalServiceUtil.
498                                                    getLayoutSetPrototypeByUuid(
499                                                            layoutSet.getLayoutSetPrototypeUuid());
500    
501                                    String allowModifications =
502                                            layoutSetPrototype.getSettingsProperty(
503                                                    "allowModifications");
504    
505                                    if (Validator.isNotNull(allowModifications)) {
506                                            return !GetterUtil.getBoolean(allowModifications);
507                                    }
508                            }
509                            catch (Exception e) {
510                            }
511                    }
512    
513                    return false;
514            }
515    
516            public static boolean isLayoutToBeUpdatedFromTemplate(Layout layout)
517                    throws Exception {
518    
519                    if (layout == null) {
520                            return false;
521                    }
522    
523                    LayoutSet layoutSet = layout.getLayoutSet();
524    
525                    if (!layoutSet.isLayoutSetPrototypeLinkEnabled()) {
526                            return false;
527                    }
528    
529                    Layout templateLayout = LayoutTypePortletImpl.getTemplateLayout(
530                            layout);
531    
532                    Date layoutModifiedDate = layout.getModifiedDate();
533    
534                    Date lastCopyDate = null;
535    
536                    String lastCopyDateString = layout.getTypeSettingsProperty(
537                            "layoutSetPrototypeLastCopyDate");
538    
539                    if (Validator.isNotNull(lastCopyDateString)) {
540                            lastCopyDate = new Date(GetterUtil.getLong(lastCopyDateString));
541                    }
542    
543                    if ((lastCopyDate != null) &&
544                            lastCopyDate.after(templateLayout.getModifiedDate())) {
545    
546                            return false;
547                    }
548    
549                    if (isLayoutLocked(layout)) {
550                            return true;
551                    }
552    
553                    if ((layoutModifiedDate == null) ||
554                            ((lastCopyDate != null) &&
555                             layoutModifiedDate.before(lastCopyDate))) {
556    
557                            return true;
558                    }
559    
560                    return false;
561            }
562    
563    }