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.portal.theme;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.util.HtmlUtil;
019    import com.liferay.portal.kernel.util.StringUtil;
020    import com.liferay.portal.kernel.util.Validator;
021    import com.liferay.portal.kernel.util.WebKeys;
022    import com.liferay.portal.model.Layout;
023    import com.liferay.portal.util.PortalUtil;
024    
025    import java.io.Serializable;
026    
027    import java.lang.reflect.Method;
028    
029    import java.util.ArrayList;
030    import java.util.List;
031    import java.util.Map;
032    
033    import javax.servlet.http.HttpServletRequest;
034    
035    /**
036     * Represents a portal navigation item, providing access to layouts and metadata
037     * from templates, which can be found in a theme's
038     * <code>portal-normal.vm</code>.
039     *
040     * @author Brian Wing Shun Chan
041     * @author Shuyang Zhou
042     */
043    public class NavItem implements Serializable {
044    
045            /**
046             * Creates a single level of navigation items from the layouts. Navigation
047             * items for nested layouts are only created when they are accessed.
048             *
049             * <p>
050             * No permission checks are performed in this method. Permissions of child
051             * layouts are honored when accessing them via {@link #getChildren()}.
052             * </p>
053             *
054             * @param  request the currently served {@link HttpServletRequest}
055             * @param  layouts the layouts from which to create the navigation items
056             * @return a single level of navigation items from the layouts, or
057             *         <code>null</code> if the collection of layouts was
058             *         <code>null</code>.
059             */
060            public static List<NavItem> fromLayouts(
061                    HttpServletRequest request, List<Layout> layouts,
062                    Map<String, Object> contextObjects) {
063    
064                    if (layouts == null) {
065                            return null;
066                    }
067    
068                    List<NavItem> navItems = new ArrayList<>(layouts.size());
069    
070                    for (Layout layout : layouts) {
071                            navItems.add(new NavItem(request, layout, contextObjects));
072                    }
073    
074                    return navItems;
075            }
076    
077            public NavItem(
078                    HttpServletRequest request, Layout layout,
079                    Map<String, Object> contextObjects) {
080    
081                    _request = request;
082                    _themeDisplay = (ThemeDisplay)request.getAttribute(
083                            WebKeys.THEME_DISPLAY);
084                    _layout = layout;
085                    _contextObjects = contextObjects;
086            }
087    
088            /**
089             * Returns all of child layouts that the current user has permission to
090             * access from this navigation item's layout.
091             *
092             * @return the list of all child layouts that the current user has
093             *         permission to access from this navigation item's layout
094             * @throws Exception if an exception occurred
095             */
096            public List<NavItem> getChildren() throws Exception {
097                    if (_children == null) {
098                            List<Layout> layouts = _layout.getChildren(
099                                    _themeDisplay.getPermissionChecker());
100    
101                            _children = fromLayouts(_request, layouts, _contextObjects);
102                    }
103    
104                    return _children;
105            }
106    
107            /**
108             * Returns the navigation item's layout.
109             *
110             * @return the navigation item's layout
111             */
112            public Layout getLayout() {
113                    return _layout;
114            }
115    
116            /**
117             * Returns the ID of the navigation item's layout.
118             *
119             * @return the ID of the navigation item's layout
120             */
121            public long getLayoutId() {
122                    return _layout.getLayoutId();
123            }
124    
125            /**
126             * Returns the HTML-escaped name of the navigation item's layout.
127             *
128             * @return the HTML-escaped name of the navigation item's layout
129             */
130            public String getName() {
131                    return HtmlUtil.escape(getUnescapedName());
132            }
133    
134            /**
135             * Returns the full, absolute URL (including the portal's URL) of the
136             * navigation item's layout.
137             *
138             * @return the full, absolute URL of the navigation item's layout
139             * @throws Exception if an exception occurred
140             */
141            public String getRegularFullURL() throws Exception {
142                    String portalURL = PortalUtil.getPortalURL(_request);
143    
144                    String regularURL = getRegularURL();
145    
146                    if (StringUtil.startsWith(regularURL, portalURL) ||
147                            Validator.isUrl(regularURL)) {
148    
149                            return regularURL;
150                    }
151                    else {
152                            return portalURL.concat(regularURL);
153                    }
154            }
155    
156            /**
157             * Returns the regular URL of the navigation item's layout.
158             *
159             * @return the regular URL of the navigation item's layout
160             * @throws Exception if an exception occurred
161             */
162            public String getRegularURL() throws Exception {
163                    return _layout.getRegularURL(_request);
164            }
165    
166            public String getResetLayoutURL() throws Exception {
167                    return _layout.getResetLayoutURL(_request);
168            }
169    
170            public String getResetMaxStateURL() throws Exception {
171                    return _layout.getResetMaxStateURL(_request);
172            }
173    
174            /**
175             * Returns the target of the navigation item's layout.
176             *
177             * @return the target of the navigation item's layout
178             */
179            public String getTarget() {
180                    return _layout.getTarget();
181            }
182    
183            /**
184             * Returns the title of the navigation item's layout in the current
185             * request's locale.
186             *
187             * @return the title of the navigation item's layout in the current
188             *         request's locale
189             */
190            public String getTitle() {
191                    return _layout.getTitle(_themeDisplay.getLocale());
192            }
193    
194            /**
195             * Returns the unescaped name of the navigation item's layout in the current
196             * request's locale.
197             *
198             * @return the unescaped name of the navigation item's layout in the current
199             *         request's locale
200             */
201            public String getUnescapedName() {
202                    return _layout.getName(_themeDisplay.getLocale());
203            }
204    
205            /**
206             * Returns the URL of the navigation item's layout, in a format that makes
207             * it safe to use the URL as an HREF attribute value
208             *
209             * @return the URL of the navigation item's layout, in a format that makes
210             *         it safe to use the URL as an HREF attribute value
211             * @throws Exception if an exception occurred
212             */
213            public String getURL() throws Exception {
214                    return HtmlUtil.escapeHREF(getRegularFullURL());
215            }
216    
217            /**
218             * Returns <code>true</code> if the navigation item's layout has child
219             * layouts.
220             *
221             * @return <code>true</code> if the navigation item's layout has child
222             *         layouts; <code>false</code> otherwise
223             * @throws Exception if an exception occurred
224             */
225            public boolean hasChildren() throws Exception {
226                    List<NavItem> children = getChildren();
227    
228                    if (!children.isEmpty()) {
229                            return true;
230                    }
231                    else {
232                            return false;
233                    }
234            }
235    
236            public void icon() throws Exception {
237                    Object velocityTaglib = _contextObjects.get("theme");
238    
239                    Method method = (Method)_contextObjects.get(
240                            "velocityTaglib_layoutIcon");
241    
242                    method.invoke(velocityTaglib, _layout);
243            }
244    
245            public boolean isChildSelected() throws PortalException {
246                    return _layout.isChildSelected(
247                            _themeDisplay.isTilesSelectable(), _themeDisplay.getLayout());
248            }
249    
250            public boolean isSelected() throws Exception {
251                    return _layout.isSelected(
252                            _themeDisplay.isTilesSelectable(), _themeDisplay.getLayout(),
253                            _themeDisplay.getLayout().getAncestorPlid());
254            }
255    
256            private List<NavItem> _children;
257            private final Map<String, Object> _contextObjects;
258            private final Layout _layout;
259            private final HttpServletRequest _request;
260            private final ThemeDisplay _themeDisplay;
261    
262    }