/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.model.impl;
import com.liferay.portal.kernel.exception.LayoutFriendlyURLException;
import com.liferay.portal.kernel.exception.NoSuchGroupException;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.language.LanguageUtil;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.ColorScheme;
import com.liferay.portal.kernel.model.Group;
import com.liferay.portal.kernel.model.GroupConstants;
import com.liferay.portal.kernel.model.Layout;
import com.liferay.portal.kernel.model.LayoutConstants;
import com.liferay.portal.kernel.model.LayoutFriendlyURL;
import com.liferay.portal.kernel.model.LayoutSet;
import com.liferay.portal.kernel.model.LayoutType;
import com.liferay.portal.kernel.model.LayoutTypeController;
import com.liferay.portal.kernel.model.LayoutTypePortlet;
import com.liferay.portal.kernel.model.LayoutTypePortletConstants;
import com.liferay.portal.kernel.model.Portlet;
import com.liferay.portal.kernel.model.PortletPreferences;
import com.liferay.portal.kernel.model.PortletWrapper;
import com.liferay.portal.kernel.model.Theme;
import com.liferay.portal.kernel.portlet.LiferayPortletURL;
import com.liferay.portal.kernel.portlet.PortalPreferences;
import com.liferay.portal.kernel.portlet.PortletURLFactoryUtil;
import com.liferay.portal.kernel.security.permission.ActionKeys;
import com.liferay.portal.kernel.security.permission.PermissionChecker;
import com.liferay.portal.kernel.service.GroupLocalServiceUtil;
import com.liferay.portal.kernel.service.LayoutFriendlyURLLocalServiceUtil;
import com.liferay.portal.kernel.service.LayoutLocalServiceUtil;
import com.liferay.portal.kernel.service.LayoutSetLocalServiceUtil;
import com.liferay.portal.kernel.service.PortletLocalServiceUtil;
import com.liferay.portal.kernel.service.PortletPreferencesLocalServiceUtil;
import com.liferay.portal.kernel.service.ThemeLocalServiceUtil;
import com.liferay.portal.kernel.service.permission.LayoutPermissionUtil;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.CharPool;
import com.liferay.portal.kernel.util.CookieKeys;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.Http;
import com.liferay.portal.kernel.util.HttpUtil;
import com.liferay.portal.kernel.util.LayoutTypePortletFactoryUtil;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.LocaleUtil;
import com.liferay.portal.kernel.util.LocalizationUtil;
import com.liferay.portal.kernel.util.PortalUtil;
import com.liferay.portal.kernel.util.PortletKeys;
import com.liferay.portal.kernel.util.PropsKeys;
import com.liferay.portal.kernel.util.ReflectionUtil;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.UnicodeProperties;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.util.LayoutClone;
import com.liferay.portal.util.LayoutCloneFactory;
import com.liferay.portal.util.LayoutTypeControllerTracker;
import com.liferay.portal.util.PropsValues;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import javax.portlet.PortletException;
import javax.portlet.PortletMode;
import javax.portlet.PortletRequest;
import javax.portlet.WindowState;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Represents a portal layout, providing access to the layout's URLs, parent
* layouts, child layouts, theme settings, type settings, and more.
*
* <p>
* The UI name for a layout is "page." Thus, a layout represents a page in the
* portal. A single page is either part of the public or private layout set of a
* group (site). Layouts can be organized hierarchically and are summarized in a
* {@link LayoutSet}.
* </p>
*
* @author Brian Wing Shun Chan
*/
public class LayoutImpl extends LayoutBaseImpl {
public static boolean hasFriendlyURLKeyword(String friendlyURL) {
String keyword = _getFriendlyURLKeyword(friendlyURL);
if (Validator.isNotNull(keyword)) {
return true;
}
return false;
}
public static int validateFriendlyURL(String friendlyURL) {
return validateFriendlyURL(friendlyURL, true);
}
/**
* Checks whether the URL is a valid friendly URL. It checks for minimal
* length and that syntactic restrictions are met, and can check that the
* URL's length does not exceed the maximum length.
*
* @param friendlyURL the URL to be checked
* @param checkMaxLength whether to check that the URL's length does not
* exceed the maximum length
* @return <code>-1</code> if the URL is a valid friendly URL; a {@link
* LayoutFriendlyURLException} constant otherwise
*/
public static int validateFriendlyURL(
String friendlyURL, boolean checkMaxLength) {
if (friendlyURL.length() < 2) {
return LayoutFriendlyURLException.TOO_SHORT;
}
if (checkMaxLength &&
(friendlyURL.length() > LayoutConstants.FRIENDLY_URL_MAX_LENGTH)) {
return LayoutFriendlyURLException.TOO_LONG;
}
if (!friendlyURL.startsWith(StringPool.SLASH)) {
return LayoutFriendlyURLException.DOES_NOT_START_WITH_SLASH;
}
if (friendlyURL.endsWith(StringPool.SLASH)) {
return LayoutFriendlyURLException.ENDS_WITH_SLASH;
}
if (friendlyURL.contains(StringPool.DOUBLE_SLASH)) {
return LayoutFriendlyURLException.ADJACENT_SLASHES;
}
for (char c : friendlyURL.toCharArray()) {
if (!Validator.isChar(c) && !Validator.isDigit(c) &&
(c != CharPool.DASH) && (c != CharPool.PERCENT) &&
(c != CharPool.PERIOD) && (c != CharPool.PLUS) &&
(c != CharPool.SLASH) && (c != CharPool.STAR) &&
(c != CharPool.UNDERLINE)) {
return LayoutFriendlyURLException.INVALID_CHARACTERS;
}
}
return -1;
}
public static void validateFriendlyURLKeyword(String friendlyURL)
throws LayoutFriendlyURLException {
String keyword = _getFriendlyURLKeyword(friendlyURL);
if (Validator.isNotNull(keyword)) {
LayoutFriendlyURLException lfurle = new LayoutFriendlyURLException(
LayoutFriendlyURLException.KEYWORD_CONFLICT);
lfurle.setKeywordConflict(keyword);
throw lfurle;
}
}
/**
* Returns all layouts that are direct or indirect children of the current
* layout.
*
* @return the layouts that are direct or indirect children of the current
* layout
*/
@Override
public List<Layout> getAllChildren() {
List<Layout> layouts = new ArrayList<>();
for (Layout layout : getChildren()) {
layouts.add(layout);
layouts.addAll(layout.getAllChildren());
}
return layouts;
}
/**
* Returns the ID of the topmost parent layout (e.g. n-th parent layout) of
* the current layout.
*
* @return the ID of the topmost parent layout of the current layout
*/
@Override
public long getAncestorLayoutId() throws PortalException {
long layoutId = 0;
Layout layout = this;
while (true) {
if (!layout.isRootLayout()) {
layout = LayoutLocalServiceUtil.getLayout(
layout.getGroupId(), layout.isPrivateLayout(),
layout.getParentLayoutId());
}
else {
layoutId = layout.getLayoutId();
break;
}
}
return layoutId;
}
/**
* Returns the plid of the topmost parent layout (e.g. n-th parent layout)
* of the current layout.
*
* @return the plid of the topmost parent layout of the current layout
*/
@Override
public long getAncestorPlid() throws PortalException {
long plid = 0;
Layout layout = this;
while (true) {
if (!layout.isRootLayout()) {
layout = LayoutLocalServiceUtil.getLayout(
layout.getGroupId(), layout.isPrivateLayout(),
layout.getParentLayoutId());
}
else {
plid = layout.getPlid();
break;
}
}
return plid;
}
/**
* Returns all parent layouts of the current layout. The list is retrieved
* recursively with the direct parent layout listed first, and most distant
* parent listed last.
*
* @return the current layout's list of parent layouts
*/
@Override
public List<Layout> getAncestors() throws PortalException {
List<Layout> layouts = Collections.emptyList();
Layout layout = this;
while (!layout.isRootLayout()) {
layout = LayoutLocalServiceUtil.getLayout(
layout.getGroupId(), layout.isPrivateLayout(),
layout.getParentLayoutId());
if (layouts.isEmpty()) {
layouts = new ArrayList<>();
}
layouts.add(layout);
}
return layouts;
}
/**
* Returns all child layouts of the current layout, independent of user
* access permissions.
*
* @return the list of all child layouts
*/
@Override
public List<Layout> getChildren() {
return LayoutLocalServiceUtil.getLayouts(
getGroupId(), isPrivateLayout(), getLayoutId());
}
/**
* Returns all child layouts of the current layout that the user has
* permission to access.
*
* @param permissionChecker the user-specific context to check permissions
* @return the list of all child layouts that the user has permission to
* access
*/
@Override
public List<Layout> getChildren(PermissionChecker permissionChecker)
throws PortalException {
List<Layout> layouts = ListUtil.copy(getChildren());
Iterator<Layout> itr = layouts.iterator();
while (itr.hasNext()) {
Layout layout = itr.next();
if (layout.isHidden() ||
!LayoutPermissionUtil.contains(
permissionChecker, layout, ActionKeys.VIEW)) {
itr.remove();
}
}
return layouts;
}
/**
* Returns the color scheme that is configured for the current layout, or
* the color scheme of the layout set that contains the current layout if no
* color scheme is configured.
*
* @return the color scheme that is configured for the current layout, or
* the color scheme of the layout set that contains the current
* layout if no color scheme is configured
*/
@Override
public ColorScheme getColorScheme() throws PortalException {
if (isInheritLookAndFeel()) {
LayoutSet layoutSet = getLayoutSet();
return layoutSet.getColorScheme();
}
else {
Theme theme = getTheme();
return ThemeLocalServiceUtil.getColorScheme(
getCompanyId(), theme.getThemeId(), getColorSchemeId());
}
}
/**
* Returns the CSS text for the current layout, or for the layout set if no
* CSS text is configured in the current layout.
*
* <p>
* Layouts and layout sets can configure CSS that is applied in addition to
* the theme's CSS.
* </p>
*
* @return the CSS text for the current layout, or for the layout set if no
* CSS text is configured in the current layout
*/
@Override
public String getCssText() throws PortalException {
if (isInheritLookAndFeel()) {
LayoutSet layoutSet = getLayoutSet();
return layoutSet.getCss();
}
else {
return getCss();
}
}
@Override
public String getDefaultThemeSetting(
String key, String device, boolean inheritLookAndFeel) {
if (!inheritLookAndFeel) {
try {
Theme theme = getTheme();
return theme.getSetting(key);
}
catch (Exception e) {
}
}
try {
LayoutSet layoutSet = getLayoutSet();
return layoutSet.getThemeSetting(key, device);
}
catch (Exception e) {
}
return StringPool.BLANK;
}
@Override
public List<Portlet> getEmbeddedPortlets() {
return getEmbeddedPortlets(getGroupId());
}
@Override
public List<Portlet> getEmbeddedPortlets(long groupId) {
List<PortletPreferences> portletPreferences = _getPortletPreferences(
groupId);
if (portletPreferences.isEmpty()) {
return Collections.emptyList();
}
List<Portlet> portlets = new ArrayList<>();
Set<String> layoutPortletIds = _getLayoutPortletIds();
for (PortletPreferences portletPreference : portletPreferences) {
String portletId = portletPreference.getPortletId();
Portlet portlet = PortletLocalServiceUtil.getPortletById(
getCompanyId(), portletId);
if ((portlet == null) || !portlet.isReady() ||
portlet.isUndeployedPortlet() || !portlet.isActive() ||
!layoutPortletIds.contains(portletId)) {
continue;
}
Portlet embeddedPortlet = portlet;
if (portlet.isInstanceable()) {
// Instanceable portlets do not need to be cloned because they
// are already cloned. See the method getPortletById in the
// class PortletLocalServiceImpl and how it references the
// method getClonedInstance in the class PortletImpl.
}
else {
portlet = new PortletWrapper(portlet) {
@Override
public boolean getStatic() {
return _staticPortlet;
}
@Override
public boolean isStatic() {
return _staticPortlet;
}
@Override
public void setStatic(boolean staticPortlet) {
_staticPortlet = staticPortlet;
}
private boolean _staticPortlet;
};
}
// We set embedded portlets as static on order to avoid adding the
// close and/or move icons.
embeddedPortlet.setStatic(true);
portlets.add(embeddedPortlet);
}
return portlets;
}
/**
* Returns the layout's friendly URL for the given locale.
*
* @param locale the locale that the friendly URL should be retrieved for
* @return the layout's friendly URL for the given locale
*/
@Override
public String getFriendlyURL(Locale locale) {
String friendlyURL = getFriendlyURL();
try {
Group group = getGroup();
UnicodeProperties typeSettingsProperties =
group.getTypeSettingsProperties();
if (!GetterUtil.getBoolean(
typeSettingsProperties.getProperty(
GroupConstants.TYPE_SETTINGS_KEY_INHERIT_LOCALES),
true)) {
String[] locales = StringUtil.split(
typeSettingsProperties.getProperty(PropsKeys.LOCALES));
if (!ArrayUtil.contains(
locales, LanguageUtil.getLanguageId(locale))) {
return friendlyURL;
}
}
LayoutFriendlyURL layoutFriendlyURL =
LayoutFriendlyURLLocalServiceUtil.getLayoutFriendlyURL(
getPlid(), LocaleUtil.toLanguageId(locale));
friendlyURL = layoutFriendlyURL.getFriendlyURL();
}
catch (Exception e) {
}
return friendlyURL;
}
/**
* Returns the friendly URLs for all configured locales.
*
* @return the friendly URLs for all configured locales
*/
@Override
public Map<Locale, String> getFriendlyURLMap() {
Map<Locale, String> friendlyURLMap = new HashMap<>();
List<LayoutFriendlyURL> layoutFriendlyURLs =
LayoutFriendlyURLLocalServiceUtil.getLayoutFriendlyURLs(getPlid());
for (LayoutFriendlyURL layoutFriendlyURL : layoutFriendlyURLs) {
friendlyURLMap.put(
LocaleUtil.fromLanguageId(layoutFriendlyURL.getLanguageId()),
layoutFriendlyURL.getFriendlyURL());
}
// If the site/portal default language changes, there may not exist a
// value for the new default language. In this situation, we will use
// the value from the previous default language.
Locale defaultSiteLocale = LocaleUtil.getSiteDefault();
if (Validator.isNull(friendlyURLMap.get(defaultSiteLocale))) {
Locale defaultLocale = LocaleUtil.fromLanguageId(
getDefaultLanguageId());
String defaultFriendlyURL = friendlyURLMap.get(defaultLocale);
friendlyURLMap.put(defaultSiteLocale, defaultFriendlyURL);
}
return friendlyURLMap;
}
@Override
public String getFriendlyURLsXML() {
Map<Locale, String> friendlyURLMap = getFriendlyURLMap();
return LocalizationUtil.updateLocalization(
friendlyURLMap, StringPool.BLANK, "FriendlyURL",
LocaleUtil.toLanguageId(LocaleUtil.getSiteDefault()));
}
/**
* Returns the current layout's group.
*
* <p>
* Group is Liferay's technical name for a site.
* </p>
*
* @return the current layout's group
*/
@Override
public Group getGroup() {
try {
return GroupLocalServiceUtil.getGroup(getGroupId());
}
catch (PortalException pe) {
return ReflectionUtil.throwException(pe);
}
}
/**
* Returns the current layout's HTML title for the given locale, or the
* current layout's name for the given locale if no HTML title is
* configured.
*
* @param locale the locale that the HTML title should be retrieved for
* @return the current layout's HTML title for the given locale, or the
* current layout's name for the given locale if no HTML title is
* configured
*/
@Override
public String getHTMLTitle(Locale locale) {
String localeLanguageId = LocaleUtil.toLanguageId(locale);
return getHTMLTitle(localeLanguageId);
}
/**
* Returns the current layout's HTML title for the given locale language ID,
* or the current layout's name if no HTML title is configured.
*
* @param localeLanguageId the locale that the HTML title should be
* retrieved for
* @return the current layout's HTML title for the given locale language ID,
* or the current layout's name if no HTML title is configured
*/
@Override
public String getHTMLTitle(String localeLanguageId) {
String htmlTitle = getTitle(localeLanguageId);
if (Validator.isNull(htmlTitle)) {
htmlTitle = getName(localeLanguageId);
}
return htmlTitle;
}
/**
* Returns <code>true</code> if the current layout has a configured icon.
*
* @return <code>true</code> if the current layout has a configured icon;
* <code>false</code> otherwise
*/
@Override
public boolean getIconImage() {
if (getIconImageId() > 0) {
return true;
}
return false;
}
/**
* Returns the current layout's {@link LayoutSet}.
*
* @return the current layout's layout set
*/
@Override
public LayoutSet getLayoutSet() {
if (_layoutSet == null) {
try {
_layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
getGroupId(), isPrivateLayout());
}
catch (PortalException pe) {
ReflectionUtil.throwException(pe);
}
}
return _layoutSet;
}
/**
* Returns the current layout's {@link LayoutType}.
*
* @return the current layout's layout type
*/
@Override
public LayoutType getLayoutType() {
if (_layoutType == null) {
_layoutType = LayoutTypePortletFactoryUtil.create(this);
}
return _layoutType;
}
/**
* Returns the current layout's linked layout.
*
* @return the current layout's linked layout, or <code>null</code> if no
* linked layout could be found
*/
@Override
public Layout getLinkedToLayout() {
long linkToLayoutId = GetterUtil.getLong(
getTypeSettingsProperty("linkToLayoutId"));
if (linkToLayoutId <= 0) {
return null;
}
return LayoutLocalServiceUtil.fetchLayout(
getGroupId(), isPrivateLayout(), linkToLayoutId);
}
/**
* Returns the current layout's parent plid.
*
* @return the current layout's parent plid, or <code>0</code> if the
* current layout is the topmost parent layout
*/
@Override
public long getParentPlid() throws PortalException {
if (getParentLayoutId() == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
return 0;
}
Layout layout = LayoutLocalServiceUtil.getLayout(
getGroupId(), isPrivateLayout(), getParentLayoutId());
return layout.getPlid();
}
@Override
public String getRegularURL(HttpServletRequest request)
throws PortalException {
String url = _getURL(request, false, false);
if (!url.startsWith(Http.HTTP) && !url.startsWith(StringPool.SLASH)) {
return StringPool.SLASH + url;
}
return url;
}
@Override
public String getResetLayoutURL(HttpServletRequest request)
throws PortalException {
return _getURL(request, true, true);
}
@Override
public String getResetMaxStateURL(HttpServletRequest request)
throws PortalException {
return _getURL(request, true, false);
}
@Override
public Group getScopeGroup() throws PortalException {
Group group = null;
try {
group = GroupLocalServiceUtil.getLayoutGroup(
getCompanyId(), getPlid());
}
catch (NoSuchGroupException nsge) {
// LPS-52675
if (_log.isDebugEnabled()) {
_log.debug(nsge, nsge);
}
}
return group;
}
@Override
public String getTarget() {
return PortalUtil.getLayoutTarget(this);
}
/**
* Returns the current layout's theme, or the layout set's theme if no
* layout theme is configured.
*
* @return the current layout's theme, or the layout set's theme if no
* layout theme is configured
*/
@Override
public Theme getTheme() throws PortalException {
if (isInheritLookAndFeel()) {
LayoutSet layoutSet = getLayoutSet();
return layoutSet.getTheme();
}
else {
return ThemeLocalServiceUtil.getTheme(getCompanyId(), getThemeId());
}
}
@Override
public String getThemeSetting(String key, String device) {
return getThemeSetting(key, device, isInheritLookAndFeel());
}
@Override
public String getThemeSetting(
String key, String device, boolean inheritLookAndFeel) {
UnicodeProperties typeSettingsProperties = getTypeSettingsProperties();
String value = typeSettingsProperties.getProperty(
ThemeSettingImpl.namespaceProperty(device, key));
if (value != null) {
return value;
}
return getDefaultThemeSetting(key, device, inheritLookAndFeel);
}
@Override
public String getTypeSettings() {
if (_typeSettingsProperties == null) {
return super.getTypeSettings();
}
else {
return _typeSettingsProperties.toString();
}
}
@Override
public UnicodeProperties getTypeSettingsProperties() {
if (_typeSettingsProperties == null) {
_typeSettingsProperties = new UnicodeProperties(true);
_typeSettingsProperties.fastLoad(super.getTypeSettings());
}
return _typeSettingsProperties;
}
@Override
public String getTypeSettingsProperty(String key) {
UnicodeProperties typeSettingsProperties = getTypeSettingsProperties();
return typeSettingsProperties.getProperty(key);
}
@Override
public String getTypeSettingsProperty(String key, String defaultValue) {
UnicodeProperties typeSettingsProperties = getTypeSettingsProperties();
return typeSettingsProperties.getProperty(key, defaultValue);
}
/**
* Returns <code>true</code> if the given layout ID matches one of the
* current layout's hierarchical parents.
*
* @param layoutId the layout ID to search for in the current layout's
* parent list
* @return <code>true</code> if the given layout ID matches one of the
* current layout's hierarchical parents; <code>false</code>
* otherwise
*/
@Override
public boolean hasAncestor(long layoutId) throws PortalException {
long parentLayoutId = getParentLayoutId();
while (parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
if (parentLayoutId == layoutId) {
return true;
}
Layout parentLayout = LayoutLocalServiceUtil.getLayout(
getGroupId(), isPrivateLayout(), parentLayoutId);
parentLayoutId = parentLayout.getParentLayoutId();
}
return false;
}
/**
* Returns <code>true</code> if the current layout has child layouts.
*
* @return <code>true</code> if the current layout has child layouts,
* <code>false</code> otherwise
*/
@Override
public boolean hasChildren() {
return LayoutLocalServiceUtil.hasLayouts(
getGroupId(), isPrivateLayout(), getLayoutId());
}
@Override
public boolean hasScopeGroup() throws PortalException {
Group group = getScopeGroup();
if (group != null) {
return true;
}
else {
return false;
}
}
@Override
public boolean hasSetModifiedDate() {
return true;
}
@Override
public boolean includeLayoutContent(
HttpServletRequest request, HttpServletResponse response)
throws Exception {
LayoutTypeController layoutTypeController =
LayoutTypeControllerTracker.getLayoutTypeController(getType());
return layoutTypeController.includeLayoutContent(
request, response, this);
}
@Override
public boolean isChildSelected(boolean selectable, Layout layout)
throws PortalException {
if (selectable) {
long plid = getPlid();
List<Layout> ancestors = layout.getAncestors();
for (Layout curLayout : ancestors) {
if (plid == curLayout.getPlid()) {
return true;
}
}
}
return false;
}
/**
* Returns <code>true</code> if the current layout can be used as a content
* display page.
*
* <p>
* A content display page must have an Asset Publisher portlet that is
* configured as the default Asset Publisher for the layout.
* </p>
*
* @return <code>true</code> if the current layout can be used as a content
* display page; <code>false</code> otherwise
*/
@Override
public boolean isContentDisplayPage() {
UnicodeProperties typeSettingsProperties = getTypeSettingsProperties();
String defaultAssetPublisherPortletId =
typeSettingsProperties.getProperty(
LayoutTypePortletConstants.DEFAULT_ASSET_PUBLISHER_PORTLET_ID);
if (Validator.isNotNull(defaultAssetPublisherPortletId)) {
return true;
}
return false;
}
@Override
public boolean isCustomizable() {
if (!isTypePortlet()) {
return false;
}
if (GetterUtil.getBoolean(
getTypeSettingsProperty(LayoutConstants.CUSTOMIZABLE_LAYOUT))) {
return true;
}
LayoutTypePortlet layoutTypePortlet =
(LayoutTypePortlet)getLayoutType();
if (layoutTypePortlet.isCustomizable()) {
return true;
}
return false;
}
/**
* Returns <code>true</code> if the current layout is the first layout in
* its parent's hierarchical list of children layouts.
*
* @return <code>true</code> if the current layout is the first layout in
* its parent's hierarchical list of children layouts;
* <code>false</code> otherwise
*/
@Override
public boolean isFirstChild() {
if (getPriority() == 0) {
return true;
}
return false;
}
/**
* Returns <code>true</code> if the current layout is the topmost parent
* layout.
*
* @return <code>true</code> if the current layout is the topmost parent
* layout; <code>false</code> otherwise
*/
@Override
public boolean isFirstParent() {
if (isFirstChild() && isRootLayout()) {
return true;
}
return false;
}
@Override
public boolean isIconImage() {
return getIconImage();
}
/**
* Returns <code>true</code> if the current layout utilizes its {@link
* LayoutSet}'s look and feel options (e.g. theme and color scheme).
*
* @return <code>true</code> if the current layout utilizes its layout set's
* look and feel options; <code>false</code> otherwise
*/
@Override
public boolean isInheritLookAndFeel() {
if (Validator.isNull(getThemeId()) ||
Validator.isNull(getColorSchemeId())) {
return true;
}
return false;
}
/**
* Returns <code>true</code> if the current layout is built from a layout
* template and still maintains an active connection to it.
*
* @return <code>true</code> if the current layout is built from a layout
* template and still maintains an active connection to it;
* <code>false</code> otherwise
*/
@Override
public boolean isLayoutPrototypeLinkActive() {
if (isLayoutPrototypeLinkEnabled() &&
Validator.isNotNull(getLayoutPrototypeUuid())) {
return true;
}
return false;
}
@Override
public boolean isPortletEmbedded(String portletId, long groupId) {
PortletPreferences portletPreferences =
PortletPreferencesLocalServiceUtil.fetchPortletPreferences(
PortletKeys.PREFS_OWNER_ID_DEFAULT,
PortletKeys.PREFS_OWNER_TYPE_LAYOUT, getPlid(), portletId);
if (portletPreferences == null) {
return false;
}
portletPreferences =
PortletPreferencesLocalServiceUtil.fetchPortletPreferences(
groupId, PortletKeys.PREFS_OWNER_TYPE_LAYOUT,
PortletKeys.PREFS_PLID_SHARED, portletId);
if ((portletPreferences == null) && isTypePortlet()) {
LayoutTypePortlet layoutTypePortlet =
(LayoutTypePortlet)getLayoutType();
PortalPreferences portalPreferences =
layoutTypePortlet.getPortalPreferences();
if ((portalPreferences != null) &&
layoutTypePortlet.isCustomizable()) {
portletPreferences =
PortletPreferencesLocalServiceUtil.fetchPortletPreferences(
portalPreferences.getUserId(),
PortletKeys.PREFS_OWNER_TYPE_USER, getPlid(),
portletId);
}
}
if (portletPreferences == null) {
return false;
}
Portlet portlet = PortletLocalServiceUtil.getPortletById(
getCompanyId(), portletId);
if ((portlet == null) || !portlet.isReady() ||
portlet.isUndeployedPortlet() || !portlet.isActive()) {
return false;
}
return true;
}
/**
* Returns <code>true</code> if the current layout is part of the public
* {@link LayoutSet}.
*
* <p>
* Note, the returned value reflects the layout's default access options,
* not its access permissions.
* </p>
*
* @return <code>true</code> if the current layout is part of the public
* layout set; <code>false</code> otherwise
*/
@Override
public boolean isPublicLayout() {
return !isPrivateLayout();
}
/**
* Returns <code>true</code> if the current layout is the root layout.
*
* @return <code>true</code> if the current layout is the root layout;
* <code>false</code> otherwise
*/
@Override
public boolean isRootLayout() {
if (getParentLayoutId() == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
return true;
}
return false;
}
@Override
public boolean isSelected(
boolean selectable, Layout layout, long ancestorPlid) {
if (selectable) {
long plid = getPlid();
if ((plid == layout.getPlid()) || (plid == ancestorPlid)) {
return true;
}
}
return false;
}
/**
* Returns <code>true</code> if the current layout can hold embedded
* portlets.
*
* @return <code>true</code> if the current layout can hold embedded
* portlets; <code>false</code> otherwise
*/
@Override
public boolean isSupportsEmbeddedPortlets() {
if (isTypeEmbedded() || isTypePanel() || isTypePortlet()) {
return true;
}
return false;
}
/**
* @deprecated As of 7.0.0, with no direct replacement
*/
@Deprecated
@Override
public boolean isTypeArticle() {
return false;
}
@Override
public boolean isTypeControlPanel() {
if (Objects.equals(getType(), LayoutConstants.TYPE_CONTROL_PANEL) ||
Objects.equals(
_getLayoutTypeControllerType(),
LayoutConstants.TYPE_CONTROL_PANEL)) {
return true;
}
return false;
}
@Override
public boolean isTypeEmbedded() {
if (Objects.equals(getType(), LayoutConstants.TYPE_EMBEDDED) ||
Objects.equals(
_getLayoutTypeControllerType(),
LayoutConstants.TYPE_EMBEDDED)) {
return true;
}
return false;
}
@Override
public boolean isTypeLinkToLayout() {
if (Objects.equals(getType(), LayoutConstants.TYPE_LINK_TO_LAYOUT) ||
Objects.equals(
_getLayoutTypeControllerType(),
LayoutConstants.TYPE_LINK_TO_LAYOUT)) {
return true;
}
return false;
}
@Override
public boolean isTypePanel() {
if (Objects.equals(getType(), LayoutConstants.TYPE_PANEL) ||
Objects.equals(
_getLayoutTypeControllerType(), LayoutConstants.TYPE_PANEL)) {
return true;
}
return false;
}
@Override
public boolean isTypePortlet() {
if (Objects.equals(getType(), LayoutConstants.TYPE_PORTLET) ||
Objects.equals(
_getLayoutTypeControllerType(), LayoutConstants.TYPE_PORTLET)) {
return true;
}
return false;
}
@Override
public boolean isTypeSharedPortlet() {
if (Objects.equals(getType(), LayoutConstants.TYPE_SHARED_PORTLET)) {
return true;
}
return false;
}
@Override
public boolean isTypeURL() {
if (Objects.equals(getType(), LayoutConstants.TYPE_URL)) {
return true;
}
return false;
}
@Override
public boolean matches(HttpServletRequest request, String friendlyURL) {
LayoutType layoutType = getLayoutType();
LayoutTypeController layoutTypeController =
layoutType.getLayoutTypeController();
return layoutTypeController.matches(request, friendlyURL, this);
}
@Override
public void setGroupId(long groupId) {
super.setGroupId(groupId);
_layoutSet = null;
}
@Override
public void setLayoutSet(LayoutSet layoutSet) {
_layoutSet = layoutSet;
}
@Override
public void setPrivateLayout(boolean privateLayout) {
super.setPrivateLayout(privateLayout);
_layoutSet = null;
}
@Override
public void setTypeSettings(String typeSettings) {
_typeSettingsProperties = null;
super.setTypeSettings(typeSettings);
}
@Override
public void setTypeSettingsProperties(
UnicodeProperties typeSettingsProperties) {
_typeSettingsProperties = typeSettingsProperties;
super.setTypeSettings(_typeSettingsProperties.toString());
}
private static String _getFriendlyURLKeyword(String friendlyURL) {
friendlyURL = StringUtil.toLowerCase(friendlyURL);
for (String keyword : _friendlyURLKeywords) {
if (friendlyURL.startsWith(keyword)) {
return keyword;
}
if (keyword.equals(friendlyURL + StringPool.SLASH)) {
return friendlyURL;
}
}
return null;
}
private static void _initFriendlyURLKeywords() {
_friendlyURLKeywords =
new String[PropsValues.LAYOUT_FRIENDLY_URL_KEYWORDS.length];
for (int i = 0; i < PropsValues.LAYOUT_FRIENDLY_URL_KEYWORDS.length;
i++) {
String keyword = PropsValues.LAYOUT_FRIENDLY_URL_KEYWORDS[i];
keyword = StringPool.SLASH + keyword;
if (!keyword.contains(StringPool.PERIOD)) {
if (keyword.endsWith(StringPool.STAR)) {
keyword = keyword.substring(0, keyword.length() - 1);
}
else {
keyword = keyword + StringPool.SLASH;
}
}
_friendlyURLKeywords[i] = StringUtil.toLowerCase(keyword);
}
}
private Set<String> _getLayoutPortletIds() {
Set<String> layoutPortletIds = new HashSet<>();
List<PortletPreferences> portletPreferences =
PortletPreferencesLocalServiceUtil.getPortletPreferences(
PortletKeys.PREFS_OWNER_ID_DEFAULT,
PortletKeys.PREFS_OWNER_TYPE_LAYOUT, getPlid());
for (PortletPreferences portletPreference : portletPreferences) {
layoutPortletIds.add(portletPreference.getPortletId());
}
return layoutPortletIds;
}
private String _getLayoutTypeControllerType() {
LayoutTypeController layoutTypeController =
LayoutTypeControllerTracker.getLayoutTypeController(getType());
return layoutTypeController.getType();
}
private LayoutTypePortlet _getLayoutTypePortletClone(
HttpServletRequest request)
throws IOException {
LayoutTypePortlet layoutTypePortlet = null;
LayoutClone layoutClone = LayoutCloneFactory.getInstance();
if (layoutClone != null) {
String typeSettings = layoutClone.get(request, getPlid());
if (typeSettings != null) {
UnicodeProperties typeSettingsProperties =
new UnicodeProperties(true);
typeSettingsProperties.load(typeSettings);
String stateMax = typeSettingsProperties.getProperty(
LayoutTypePortletConstants.STATE_MAX);
String stateMin = typeSettingsProperties.getProperty(
LayoutTypePortletConstants.STATE_MIN);
Layout layout = (Layout)clone();
layoutTypePortlet = (LayoutTypePortlet)layout.getLayoutType();
layoutTypePortlet.setStateMax(stateMax);
layoutTypePortlet.setStateMin(stateMin);
}
}
if (layoutTypePortlet == null) {
layoutTypePortlet = (LayoutTypePortlet)getLayoutType();
}
return layoutTypePortlet;
}
private List<PortletPreferences> _getPortletPreferences(long groupId) {
List<PortletPreferences> portletPreferences =
PortletPreferencesLocalServiceUtil.getPortletPreferences(
groupId, PortletKeys.PREFS_OWNER_TYPE_LAYOUT,
PortletKeys.PREFS_PLID_SHARED);
if (isTypePortlet()) {
LayoutTypePortlet layoutTypePortlet =
(LayoutTypePortlet)getLayoutType();
PortalPreferences portalPreferences =
layoutTypePortlet.getPortalPreferences();
if ((portalPreferences != null) &&
layoutTypePortlet.isCustomizable()) {
portletPreferences = ListUtil.copy(portletPreferences);
portletPreferences.addAll(
PortletPreferencesLocalServiceUtil.getPortletPreferences(
portalPreferences.getUserId(),
PortletKeys.PREFS_OWNER_TYPE_USER, getPlid()));
}
}
return portletPreferences;
}
private String _getURL(
HttpServletRequest request, boolean resetMaxState,
boolean resetRenderParameters)
throws PortalException {
ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
WebKeys.THEME_DISPLAY);
if (resetMaxState) {
Layout layout = themeDisplay.getLayout();
LayoutTypePortlet layoutTypePortlet = null;
if (layout.equals(this)) {
layoutTypePortlet = themeDisplay.getLayoutTypePortlet();
}
else {
try {
layoutTypePortlet = _getLayoutTypePortletClone(request);
}
catch (IOException ioe) {
_log.error("Unable to clone layout settings", ioe);
layoutTypePortlet = (LayoutTypePortlet)getLayoutType();
}
}
if (layoutTypePortlet.hasStateMax()) {
String portletId = StringUtil.split(
layoutTypePortlet.getStateMax())[0];
LiferayPortletURL portletURL = PortletURLFactoryUtil.create(
request, portletId, this, PortletRequest.ACTION_PHASE);
try {
portletURL.setWindowState(WindowState.NORMAL);
portletURL.setPortletMode(PortletMode.VIEW);
}
catch (PortletException pe) {
throw new SystemException(pe);
}
portletURL.setAnchor(false);
if (PropsValues.LAYOUT_DEFAULT_P_L_RESET &&
!resetRenderParameters) {
portletURL.setParameter("p_l_reset", "0");
}
else if (!PropsValues.LAYOUT_DEFAULT_P_L_RESET &&
resetRenderParameters) {
portletURL.setParameter("p_l_reset", "1");
}
return portletURL.toString();
}
}
String url = PortalUtil.getLayoutURL(this, themeDisplay);
if (!CookieKeys.hasSessionId(request)) {
String portalURL = PortalUtil.getPortalURL(request);
if (url.startsWith(portalURL) || url.startsWith(StringPool.SLASH)) {
HttpSession session = request.getSession();
url = PortalUtil.getURLWithSessionId(url, session.getId());
}
}
if (!resetMaxState) {
return url;
}
if (PropsValues.LAYOUT_DEFAULT_P_L_RESET && !resetRenderParameters) {
url = HttpUtil.addParameter(url, "p_l_reset", 0);
}
else if (!PropsValues.LAYOUT_DEFAULT_P_L_RESET &&
resetRenderParameters) {
url = HttpUtil.addParameter(url, "p_l_reset", 1);
}
return url;
}
private static final Log _log = LogFactoryUtil.getLog(LayoutImpl.class);
private static String[] _friendlyURLKeywords;
static {
_initFriendlyURLKeywords();
}
private LayoutSet _layoutSet;
private transient LayoutType _layoutType;
private UnicodeProperties _typeSettingsProperties;
}