001    /**
002     * Copyright (c) 2000-2013 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.taglib.ui;
016    
017    import com.liferay.portal.kernel.language.LanguageUtil;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.servlet.taglib.ui.BreadcrumbEntry;
021    import com.liferay.portal.kernel.util.CookieKeys;
022    import com.liferay.portal.kernel.util.GetterUtil;
023    import com.liferay.portal.kernel.util.HtmlUtil;
024    import com.liferay.portal.kernel.util.HttpUtil;
025    import com.liferay.portal.kernel.util.PropsKeys;
026    import com.liferay.portal.kernel.util.PropsUtil;
027    import com.liferay.portal.kernel.util.StringBundler;
028    import com.liferay.portal.kernel.util.StringPool;
029    import com.liferay.portal.kernel.util.StringUtil;
030    import com.liferay.portal.kernel.util.Validator;
031    import com.liferay.portal.kernel.util.WebKeys;
032    import com.liferay.portal.model.Account;
033    import com.liferay.portal.model.Group;
034    import com.liferay.portal.model.GroupConstants;
035    import com.liferay.portal.model.Layout;
036    import com.liferay.portal.model.LayoutConstants;
037    import com.liferay.portal.model.LayoutSet;
038    import com.liferay.portal.model.Organization;
039    import com.liferay.portal.model.User;
040    import com.liferay.portal.service.GroupLocalServiceUtil;
041    import com.liferay.portal.service.LayoutLocalServiceUtil;
042    import com.liferay.portal.service.LayoutSetLocalServiceUtil;
043    import com.liferay.portal.service.OrganizationLocalServiceUtil;
044    import com.liferay.portal.service.UserLocalServiceUtil;
045    import com.liferay.portal.theme.PortletDisplay;
046    import com.liferay.portal.theme.ThemeDisplay;
047    import com.liferay.portal.util.PortalUtil;
048    import com.liferay.taglib.aui.AUIUtil;
049    import com.liferay.taglib.util.IncludeTag;
050    
051    import java.util.List;
052    import java.util.Map;
053    
054    import javax.portlet.PortletURL;
055    
056    import javax.servlet.http.HttpServletRequest;
057    import javax.servlet.http.HttpSession;
058    
059    /**
060     * @author Brian Wing Shun Chan
061     */
062    public class BreadcrumbTag extends IncludeTag {
063    
064            public void setPortletURL(PortletURL portletURL) {
065                    _portletURL = portletURL;
066            }
067    
068            public void setSelLayout(Layout selLayout) {
069                    _selLayout = selLayout;
070            }
071    
072            public void setSelLayoutParam(String selLayoutParam) {
073                    _selLayoutParam = selLayoutParam;
074            }
075    
076            public void setShowCurrentGroup(boolean showCurrentGroup) {
077                    _showCurrentGroup = showCurrentGroup;
078            }
079    
080            public void setShowCurrentPortlet(boolean showCurrentPortlet) {
081                    _showCurrentPortlet = showCurrentPortlet;
082            }
083    
084            public void setShowGuestGroup(boolean showGuestGroup) {
085                    _showGuestGroup = showGuestGroup;
086            }
087    
088            public void setShowLayout(boolean showLayout) {
089                    _showLayout = showLayout;
090            }
091    
092            public void setShowParentGroups(boolean showParentGroups) {
093                    _showParentGroups = showParentGroups;
094            }
095    
096            public void setShowPortletBreadcrumb(boolean showPortletBreadcrumb) {
097                    _showPortletBreadcrumb = showPortletBreadcrumb;
098            }
099    
100            protected void buildGuestGroupBreadcrumb(
101                            ThemeDisplay themeDisplay, StringBundler sb)
102                    throws Exception {
103    
104                    Group group = GroupLocalServiceUtil.getGroup(
105                            themeDisplay.getCompanyId(), GroupConstants.GUEST);
106    
107                    if (group.getPublicLayoutsPageCount() == 0) {
108                            return;
109                    }
110    
111                    sb.append("<li><a href=\"");
112    
113                    LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
114                            group.getGroupId(), false);
115    
116                    String layoutSetFriendlyURL = PortalUtil.getLayoutSetFriendlyURL(
117                            layoutSet, themeDisplay);
118    
119                    if (themeDisplay.isAddSessionIdToURL()) {
120                            layoutSetFriendlyURL = PortalUtil.getURLWithSessionId(
121                                    layoutSetFriendlyURL, themeDisplay.getSessionId());
122                    }
123    
124                    sb.append(layoutSetFriendlyURL);
125    
126                    sb.append("\">");
127    
128                    Account account = themeDisplay.getAccount();
129    
130                    sb.append(HtmlUtil.escape(account.getName()));
131    
132                    sb.append("</a><span class=\"divider\">/</span></li>");
133            }
134    
135            protected void buildLayoutBreadcrumb(
136                            Layout selLayout, String selLayoutParam, boolean selectedLayout,
137                            PortletURL portletURL, ThemeDisplay themeDisplay, StringBundler sb)
138                    throws Exception {
139    
140                    if (selLayout.getParentLayoutId() !=
141                                    LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
142    
143                            Layout parentLayout = LayoutLocalServiceUtil.getParentLayout(
144                                    selLayout);
145    
146                            buildLayoutBreadcrumb(
147                                    parentLayout, selLayoutParam, false, portletURL, themeDisplay,
148                                    sb);
149                    }
150    
151                    sb.append("<li><a href=\"");
152    
153                    String layoutURL = getBreadcrumbLayoutURL(
154                            selLayout, selLayoutParam, portletURL, themeDisplay);
155    
156                    if (themeDisplay.isAddSessionIdToURL()) {
157                            layoutURL = PortalUtil.getURLWithSessionId(
158                                    layoutURL, themeDisplay.getSessionId());
159                    }
160    
161                    if (selLayout.isTypeControlPanel()) {
162                            layoutURL = HttpUtil.removeParameter(
163                                    layoutURL, "controlPanelCategory");
164                    }
165    
166                    sb.append(layoutURL);
167    
168                    sb.append("\" ");
169    
170                    String layoutName = selLayout.getName(themeDisplay.getLocale());
171    
172                    if (selLayout.isTypeControlPanel()) {
173                            sb.append("target=\"_top\"");
174    
175                            if (layoutName.equals(LayoutConstants.NAME_CONTROL_PANEL_DEFAULT)) {
176                                    layoutName = LanguageUtil.get(
177                                            themeDisplay.getLocale(), "control-panel");
178                            }
179                    }
180                    else {
181                            String target = PortalUtil.getLayoutTarget(selLayout);
182    
183                            sb.append(target);
184                    }
185    
186                    sb.append(StringPool.GREATER_THAN);
187                    sb.append(HtmlUtil.escape(layoutName));
188                    sb.append("</a><span class=\"divider\">/</span></li>");
189            }
190    
191            protected void buildParentGroupsBreadcrumb(
192                            LayoutSet layoutSet, PortletURL portletURL,
193                            ThemeDisplay themeDisplay, StringBundler sb)
194                    throws Exception {
195    
196                    Group group = layoutSet.getGroup();
197    
198                    if (group.isControlPanel()) {
199                            return;
200                    }
201    
202                    if (group.isSite()) {
203                            Group parentSite = group.getParentGroup();
204    
205                            if (parentSite != null) {
206                                    LayoutSet parentLayoutSet =
207                                            LayoutSetLocalServiceUtil.getLayoutSet(
208                                                    parentSite.getGroupId(), layoutSet.isPrivateLayout());
209    
210                                    buildParentGroupsBreadcrumb(
211                                            parentLayoutSet, portletURL, themeDisplay, sb);
212                            }
213                    }
214                    else if (group.isUser()) {
215                            User groupUser = UserLocalServiceUtil.getUser(group.getClassPK());
216    
217                            List<Organization> organizations =
218                                    OrganizationLocalServiceUtil.getUserOrganizations(
219                                            groupUser.getUserId());
220    
221                            if (!organizations.isEmpty()) {
222                                    Organization organization = organizations.get(0);
223    
224                                    Group parentGroup = organization.getGroup();
225    
226                                    LayoutSet parentLayoutSet =
227                                            LayoutSetLocalServiceUtil.getLayoutSet(
228                                                    parentGroup.getGroupId(), layoutSet.isPrivateLayout());
229    
230                                    buildParentGroupsBreadcrumb(
231                                            parentLayoutSet, portletURL, themeDisplay, sb);
232                            }
233                    }
234    
235                    int layoutsPageCount = 0;
236    
237                    if (layoutSet.isPrivateLayout()) {
238                            layoutsPageCount = group.getPrivateLayoutsPageCount();
239                    }
240                    else {
241                            layoutsPageCount = group.getPublicLayoutsPageCount();
242                    }
243    
244                    if ((layoutsPageCount > 0) && !group.isGuest()) {
245                            String layoutSetFriendlyURL = PortalUtil.getLayoutSetFriendlyURL(
246                                    layoutSet, themeDisplay);
247    
248                            if (themeDisplay.isAddSessionIdToURL()) {
249                                    layoutSetFriendlyURL = PortalUtil.getURLWithSessionId(
250                                            layoutSetFriendlyURL, themeDisplay.getSessionId());
251                            }
252    
253                            sb.append("<li><a href=\"");
254                            sb.append(layoutSetFriendlyURL);
255                            sb.append("\">");
256                            sb.append(HtmlUtil.escape(group.getDescriptiveName()));
257                            sb.append("</a><span class=\"divider\">/</span></li>");
258                    }
259            }
260    
261            protected void buildPortletBreadcrumb(
262                            HttpServletRequest request, boolean showCurrentGroup,
263                            boolean showCurrentPortlet, ThemeDisplay themeDisplay,
264                            StringBundler sb)
265                    throws Exception {
266    
267                    List<BreadcrumbEntry> breadcrumbEntries =
268                            PortalUtil.getPortletBreadcrumbs(request);
269    
270                    if (breadcrumbEntries == null) {
271                            return;
272                    }
273    
274                    for (int i = 0; i < breadcrumbEntries.size(); i++) {
275                            BreadcrumbEntry breadcrumbEntry = breadcrumbEntries.get(i);
276    
277                            Map<String, Object> data = breadcrumbEntry.getData();
278    
279                            String breadcrumbTitle = breadcrumbEntry.getTitle();
280                            String breadcrumbURL = breadcrumbEntry.getURL();
281    
282                            if (!showCurrentGroup) {
283                                    String siteGroupName = themeDisplay.getSiteGroupName();
284    
285                                    if (siteGroupName.equals(breadcrumbTitle)) {
286                                            continue;
287                                    }
288                            }
289    
290                            if (!showCurrentPortlet) {
291                                    PortletDisplay portletDisplay =
292                                            themeDisplay.getPortletDisplay();
293    
294                                    String portletTitle = PortalUtil.getPortletTitle(
295                                            portletDisplay.getId(), themeDisplay.getUser());
296    
297                                    if (portletTitle.equals(breadcrumbTitle)) {
298                                            continue;
299                                    }
300                            }
301    
302                            if (!CookieKeys.hasSessionId(request) &&
303                                    Validator.isNotNull(breadcrumbURL)) {
304    
305                                    HttpSession session = request.getSession();
306    
307                                    breadcrumbURL = PortalUtil.getURLWithSessionId(
308                                            breadcrumbURL, session.getId());
309                            }
310    
311                            sb.append("<li>");
312    
313                            if (i < (breadcrumbEntries.size() - 1)) {
314                                    if (Validator.isNotNull(breadcrumbURL)) {
315                                            sb.append("<a href=\"");
316                                            sb.append(HtmlUtil.escape(breadcrumbURL));
317                                            sb.append("\"");
318                                            sb.append(AUIUtil.buildData(data));
319                                            sb.append(">");
320                                    }
321    
322                                    sb.append(HtmlUtil.escape(breadcrumbTitle));
323    
324                                    if (Validator.isNotNull(breadcrumbURL)) {
325                                            sb.append("</a>");
326                                    }
327    
328                                    sb.append("<span class=\"divider\">/</span>");
329                            }
330                            else {
331                                    sb.append(HtmlUtil.escape(breadcrumbTitle));
332                            }
333    
334                            sb.append("</li>");
335                    }
336            }
337    
338            @Override
339            protected void cleanUp() {
340                    _portletURL = null;
341                    _selLayout = null;
342                    _selLayoutParam = null;
343                    _showCurrentGroup = true;
344                    _showCurrentPortlet = true;
345                    _showGuestGroup = _SHOW_GUEST_GROUP;
346                    _showLayout = true;
347                    _showParentGroups = _SHOW_PARENT_GROUPS;
348                    _showPortletBreadcrumb = true;
349            }
350    
351            protected String getBreadcrumbLayoutURL(
352                            Layout selLayout, String selLayoutParam, PortletURL portletURL,
353                            ThemeDisplay themeDisplay)
354                    throws Exception {
355    
356                    if (portletURL == null) {
357                            return PortalUtil.getLayoutFullURL(selLayout, themeDisplay);
358                    }
359    
360                    portletURL.setParameter(
361                            selLayoutParam, String.valueOf(selLayout.getPlid()));
362    
363                    if (selLayout.isTypeControlPanel()) {
364                            if (themeDisplay.getDoAsGroupId() > 0) {
365                                    portletURL.setParameter(
366                                            "doAsGroupId",
367                                            String.valueOf(themeDisplay.getDoAsGroupId()));
368                            }
369    
370                            if (themeDisplay.getRefererPlid() != LayoutConstants.DEFAULT_PLID) {
371                                    portletURL.setParameter(
372                                            "refererPlid",
373                                            String.valueOf(themeDisplay.getRefererPlid()));
374                            }
375                    }
376    
377                    return portletURL.toString();
378            }
379    
380            protected String getBreadcrumbString(HttpServletRequest request) {
381                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
382                            WebKeys.THEME_DISPLAY);
383    
384                    StringBundler sb = new StringBundler();
385    
386                    try {
387                            if (Validator.isNull(_selLayout)) {
388                                    setSelLayout(themeDisplay.getLayout());
389                            }
390    
391                            Group group = _selLayout.getGroup();
392    
393                            if (_showGuestGroup) {
394                                    buildGuestGroupBreadcrumb(themeDisplay, sb);
395                            }
396    
397                            if (_showParentGroups) {
398                                    buildParentGroupsBreadcrumb(
399                                            _selLayout.getLayoutSet(), _portletURL, themeDisplay, sb);
400                            }
401    
402                            if (_showLayout && !group.isLayoutPrototype()) {
403                                    buildLayoutBreadcrumb(
404                                            _selLayout, _selLayoutParam, true, _portletURL,
405                                            themeDisplay, sb);
406                            }
407    
408                            if (_showPortletBreadcrumb) {
409                                    buildPortletBreadcrumb(
410                                            request, _showCurrentGroup, _showCurrentPortlet,
411                                            themeDisplay, sb);
412                            }
413                    }
414                    catch (Exception e) {
415                            _log.error(e, e);
416                    }
417    
418                    String breadcrumbString = sb.toString();
419    
420                    if (Validator.isNull(breadcrumbString)) {
421                            return StringPool.BLANK;
422                    }
423    
424                    int x = breadcrumbString.indexOf("<li") + 3;
425                    int y = breadcrumbString.lastIndexOf("<li") + 3;
426    
427                    if (x == y) {
428                            breadcrumbString = StringUtil.insert(
429                                    breadcrumbString, " class=\"active only\"", x);
430                    }
431                    else {
432                            breadcrumbString = StringUtil.insert(
433                                    breadcrumbString, " class=\"active last\"", y);
434                            breadcrumbString = StringUtil.insert(
435                                    breadcrumbString, " class=\"first\"", x);
436                    }
437    
438                    return breadcrumbString;
439            }
440    
441            @Override
442            protected String getPage() {
443                    return _PAGE;
444            }
445    
446            @Override
447            protected void setAttributes(HttpServletRequest request) {
448                    request.setAttribute(
449                            "liferay-ui:breadcrumb:breadcrumbString",
450                            getBreadcrumbString(request));
451                    request.setAttribute("liferay-ui:breadcrumb:portletURL", _portletURL);
452                    request.setAttribute("liferay-ui:breadcrumb:selLayout", _selLayout);
453                    request.setAttribute(
454                            "liferay-ui:breadcrumb:selLayoutParam", _selLayoutParam);
455                    request.setAttribute(
456                            "liferay-ui:breadcrumb:showCurrentGroup",
457                            String.valueOf(_showCurrentGroup));
458                    request.setAttribute(
459                            "liferay-ui:breadcrumb:showCurrentPortlet",
460                            String.valueOf(_showCurrentPortlet));
461                    request.setAttribute(
462                            "liferay-ui:breadcrumb:showGuestGroup",
463                            String.valueOf(_showGuestGroup));
464                    request.setAttribute(
465                            "liferay-ui:breadcrumb:showLayout", String.valueOf(_showLayout));
466                    request.setAttribute(
467                            "liferay-ui:breadcrumb:showParentGroups",
468                            String.valueOf(_showParentGroups));
469                    request.setAttribute(
470                            "liferay-ui:breadcrumb:showPortletBreadcrumb",
471                            String.valueOf(_showPortletBreadcrumb));
472            }
473    
474            private static final String _PAGE = "/html/taglib/ui/breadcrumb/page.jsp";
475    
476            private static final boolean _SHOW_GUEST_GROUP = GetterUtil.getBoolean(
477                    PropsUtil.get(PropsKeys.BREADCRUMB_SHOW_GUEST_GROUP));
478    
479            private static final boolean _SHOW_PARENT_GROUPS = GetterUtil.getBoolean(
480                    PropsUtil.get(PropsKeys.BREADCRUMB_SHOW_PARENT_GROUPS));
481    
482            private static Log _log = LogFactoryUtil.getLog(BreadcrumbTag.class);
483    
484            private PortletURL _portletURL;
485            private Layout _selLayout;
486            private String _selLayoutParam;
487            private boolean _showCurrentGroup = true;
488            private boolean _showCurrentPortlet = true;
489            private boolean _showGuestGroup = _SHOW_GUEST_GROUP;
490            private boolean _showLayout = true;
491            private boolean _showParentGroups = _SHOW_PARENT_GROUPS;
492            private boolean _showPortletBreadcrumb = true;
493    
494    }