/** * 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.counter.kernel.service.CounterLocalServiceUtil; import com.liferay.portal.kernel.configuration.Filter; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.exception.SystemException; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.model.CustomizedPages; import com.liferay.portal.kernel.model.Group; import com.liferay.portal.kernel.model.Layout; import com.liferay.portal.kernel.model.LayoutSet; import com.liferay.portal.kernel.model.LayoutTemplate; import com.liferay.portal.kernel.model.LayoutTypeAccessPolicy; 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.Plugin; import com.liferay.portal.kernel.model.Portlet; import com.liferay.portal.kernel.model.PortletConstants; import com.liferay.portal.kernel.model.PortletPreferencesIds; import com.liferay.portal.kernel.model.PortletWrapper; import com.liferay.portal.kernel.model.ResourcePermission; import com.liferay.portal.kernel.portlet.PortalPreferences; import com.liferay.portal.kernel.portlet.PortletLayoutListener; import com.liferay.portal.kernel.portlet.PortletPreferencesFactoryUtil; import com.liferay.portal.kernel.security.permission.ActionKeys; import com.liferay.portal.kernel.security.permission.PermissionChecker; import com.liferay.portal.kernel.security.permission.PermissionThreadLocal; import com.liferay.portal.kernel.service.LayoutTemplateLocalServiceUtil; import com.liferay.portal.kernel.service.PluginSettingLocalServiceUtil; import com.liferay.portal.kernel.service.PortletLocalServiceUtil; import com.liferay.portal.kernel.service.PortletPreferencesLocalServiceUtil; import com.liferay.portal.kernel.service.ResourcePermissionLocalServiceUtil; import com.liferay.portal.kernel.service.permission.LayoutPermissionUtil; import com.liferay.portal.kernel.service.permission.PortletPermissionUtil; import com.liferay.portal.kernel.util.ArrayUtil; import com.liferay.portal.kernel.util.DateFormatFactoryUtil; import com.liferay.portal.kernel.util.FastDateFormatFactoryUtil; import com.liferay.portal.kernel.util.GetterUtil; import com.liferay.portal.kernel.util.LayoutTypePortletFactoryUtil; import com.liferay.portal.kernel.util.ListUtil; 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.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.util.PropsUtil; import com.liferay.portal.util.PropsValues; import com.liferay.sites.kernel.util.SitesUtil; import com.liferay.util.JS; import java.text.DateFormat; import java.text.Format; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; /** * @author Brian Wing Shun Chan * @author Berentey Zsolt * @author Jorge Ferrer * @author Raymond Augé */ public class LayoutTypePortletImpl extends LayoutTypeImpl implements LayoutTypePortlet { public LayoutTypePortletImpl( Layout layout, LayoutTypeController layoutTypeController, LayoutTypeAccessPolicy layoutTypeAccessPolicy) { super(layout, layoutTypeController, layoutTypeAccessPolicy); } @Override public void addModeAboutPortletId(String portletId) { removeModesPortletId(portletId); setModeAbout(StringUtil.add(getModeAbout(), portletId)); } @Override public void addModeConfigPortletId(String portletId) { removeModesPortletId(portletId); setModeConfig(StringUtil.add(getModeConfig(), portletId)); } @Override public void addModeEditDefaultsPortletId(String portletId) { removeModesPortletId(portletId); setModeEditDefaults(StringUtil.add(getModeEditDefaults(), portletId)); } @Override public void addModeEditGuestPortletId(String portletId) { removeModesPortletId(portletId); setModeEditGuest(StringUtil.add(getModeEditGuest(), portletId)); } @Override public void addModeEditPortletId(String portletId) { removeModesPortletId(portletId); setModeEdit(StringUtil.add(getModeEdit(), portletId)); } @Override public void addModeHelpPortletId(String portletId) { removeModesPortletId(portletId); setModeHelp(StringUtil.add(getModeHelp(), portletId)); } @Override public void addModePreviewPortletId(String portletId) { removeModesPortletId(portletId); setModePreview(StringUtil.add(getModePreview(), portletId)); } @Override public void addModePrintPortletId(String portletId) { removeModesPortletId(portletId); setModePrint(StringUtil.add(getModePrint(), portletId)); } @Override public String addPortletId(long userId, String portletId) { return addPortletId(userId, portletId, true); } @Override public String addPortletId( long userId, String portletId, boolean checkPermission) { return addPortletId(userId, portletId, null, -1, checkPermission); } @Override public String addPortletId( long userId, String portletId, String columnId, int columnPos) { return addPortletId(userId, portletId, columnId, columnPos, true); } @Override public String addPortletId( long userId, String portletId, String columnId, int columnPos, boolean checkPermission) { return addPortletId( userId, portletId, columnId, columnPos, checkPermission, false); } @Override public void addPortletIds( long userId, String[] portletIds, boolean checkPermission) { for (String portletId : portletIds) { addPortletId(userId, portletId, checkPermission); } } @Override public void addPortletIds( long userId, String[] portletIds, String columnId, boolean checkPermission) { for (String portletId : portletIds) { addPortletId(userId, portletId, columnId, -1, checkPermission); } } @Override public void addStateMaxPortletId(String portletId) { removeStatesPortletId(portletId); //setStateMax(StringUtil.add(getStateMax(), portletId)); setStateMax(StringUtil.add(StringPool.BLANK, portletId)); } @Override public void addStateMinPortletId(String portletId) { removeStateMaxPortletId(portletId); setStateMin(StringUtil.add(getStateMin(), portletId)); } @Override public List<Portlet> addStaticPortlets( List<Portlet> portlets, List<Portlet> startPortlets, List<Portlet> endPortlets) { // Return the original array of portlets if no static portlets are // specified if (startPortlets == null) { startPortlets = new ArrayList<>(); } if (endPortlets == null) { endPortlets = new ArrayList<>(); } if (startPortlets.isEmpty() && endPortlets.isEmpty()) { return portlets; } // New array of portlets that contain the static portlets List<Portlet> list = new ArrayList<>( portlets.size() + startPortlets.size() + endPortlets.size()); if (!startPortlets.isEmpty()) { list.addAll(startPortlets); } for (int i = 0; i < portlets.size(); i++) { Portlet portlet = portlets.get(i); // Add the portlet if and only if it is not also a static portlet if (!startPortlets.contains(portlet) && !endPortlets.contains(portlet)) { list.add(portlet); } } if (!endPortlets.isEmpty()) { list.addAll(endPortlets); } return list; } @Override public List<Portlet> getAllPortlets() { List<Portlet> explicitlyAddedPortlets = getExplicitlyAddedPortlets(); List<Portlet> staticPortlets = getStaticPortlets( PropsKeys.LAYOUT_STATIC_PORTLETS_ALL); List<Portlet> embeddedPortlets = getEmbeddedPortlets(); return addStaticPortlets( explicitlyAddedPortlets, staticPortlets, embeddedPortlets); } @Override public List<Portlet> getAllPortlets(boolean includeSystem) { List<Portlet> portlets = getAllPortlets(); if (includeSystem) { return portlets; } List<Portlet> filteredPortlets = new ArrayList<>(); for (Portlet portlet : portlets) { if (portlet.isSystem() && !includeSystem) { continue; } filteredPortlets.add(portlet); } return filteredPortlets; } @Override public List<Portlet> getAllPortlets(String columnId) { String columnValue = getColumnValue(columnId); String[] portletIds = StringUtil.split(columnValue); List<Portlet> portlets = new ArrayList<>(portletIds.length); for (String portletId : portletIds) { Portlet portlet = PortletLocalServiceUtil.getPortletById( getCompanyId(), portletId); if (portlet != null) { portlets.add(portlet); } } List<Portlet> startPortlets = getStaticPortlets( PropsKeys.LAYOUT_STATIC_PORTLETS_START + columnId); List<Portlet> endPortlets = getStaticPortlets( PropsKeys.LAYOUT_STATIC_PORTLETS_END + columnId); return addStaticPortlets(portlets, startPortlets, endPortlets); } @Override public List<Portlet> getEmbeddedPortlets() { Layout layout = getLayout(); return layout.getEmbeddedPortlets(); } @Override public List<Portlet> getExplicitlyAddedPortlets() { List<Portlet> portlets = new ArrayList<>(); List<String> columns = getColumns(); for (int i = 0; i < columns.size(); i++) { String columnId = columns.get(i); portlets.addAll(getAllPortlets(columnId)); } return portlets; } @Override public Layout getLayoutSetPrototypeLayout() { if (_layoutSetPrototypeLayout == null) { _layoutSetPrototypeLayout = SitesUtil.getLayoutSetPrototypeLayout( getLayout()); if (_layoutSetPrototypeLayout == null) { _layoutSetPrototypeLayout = _nullLayout; } } if (_layoutSetPrototypeLayout == _nullLayout) { return null; } return _layoutSetPrototypeLayout; } @Override public String getLayoutSetPrototypeLayoutProperty(String key) { Layout layoutSetPrototypeLayout = getLayoutSetPrototypeLayout(); if (layoutSetPrototypeLayout == null) { return StringPool.BLANK; } UnicodeProperties typeSettingsProperties = layoutSetPrototypeLayout.getTypeSettingsProperties(); return typeSettingsProperties.getProperty(key); } @Override public LayoutTemplate getLayoutTemplate() { String themeId = getThemeId(); LayoutTemplate layoutTemplate = LayoutTemplateLocalServiceUtil.getLayoutTemplate( getLayoutTemplateId(), false, themeId); if (layoutTemplate == null) { layoutTemplate = new LayoutTemplateImpl( StringPool.BLANK, StringPool.BLANK); List<String> columns = new ArrayList<>(10); for (int i = 1; i <= 10; i++) { columns.add(LayoutTypePortletConstants.COLUMN_PREFIX + i); } layoutTemplate.setColumns(columns); } return layoutTemplate; } @Override public String getLayoutTemplateId() { return GetterUtil.getString( getTypeSettingsProperty( LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID)); } @Override public String getModeAbout() { return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_ABOUT); } @Override public String getModeConfig() { return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_CONFIG); } @Override public String getModeEdit() { return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_EDIT); } @Override public String getModeEditDefaults() { return getTypeSettingsProperty( LayoutTypePortletConstants.MODE_EDIT_DEFAULTS); } @Override public String getModeEditGuest() { return getTypeSettingsProperty( LayoutTypePortletConstants.MODE_EDIT_GUEST); } @Override public String getModeHelp() { return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_HELP); } @Override public String getModePreview() { return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_PREVIEW); } @Override public String getModePrint() { return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_PRINT); } @Override public int getNumOfColumns() { LayoutTemplate layoutTemplate = getLayoutTemplate(); List<String> columns = layoutTemplate.getColumns(); return columns.size(); } @Override public PortalPreferences getPortalPreferences() { return _portalPreferences; } @Override public List<String> getPortletIds() { List<String> portletIds = new ArrayList<>(); List<String> columns = getColumns(); for (int i = 0; i < columns.size(); i++) { String columnId = columns.get(i); String columnValue = getColumnValue(columnId); portletIds.addAll( ListUtil.fromArray(StringUtil.split(columnValue))); } return portletIds; } @Override public List<Portlet> getPortlets() { List<String> portletIds = getPortletIds(); List<Portlet> portlets = new ArrayList<>(portletIds.size()); for (int i = 0; i < portletIds.size(); i++) { String portletId = portletIds.get(i); Portlet portlet = PortletLocalServiceUtil.getPortletById( getCompanyId(), portletId); if (portlet != null) { portlets.add(portlet); } } return portlets; } @Override public String getStateMax() { return getTypeSettingsProperty(LayoutTypePortletConstants.STATE_MAX); } @Override public String getStateMaxPortletId() { String[] stateMax = StringUtil.split(getStateMax()); if (stateMax.length > 0) { return stateMax[0]; } else { return StringPool.BLANK; } } @Override public String getStateMin() { return getTypeSettingsProperty(LayoutTypePortletConstants.STATE_MIN); } @Override public boolean hasDefaultScopePortletId(long groupId, String portletId) { if (hasPortletId(portletId)) { long scopeGroupId = PortalUtil.getScopeGroupId( getLayout(), portletId); if (groupId == scopeGroupId) { return true; } } return false; } @Override public boolean hasModeAboutPortletId(String portletId) { return StringUtil.contains(getModeAbout(), portletId); } @Override public boolean hasModeConfigPortletId(String portletId) { return StringUtil.contains(getModeConfig(), portletId); } @Override public boolean hasModeEditDefaultsPortletId(String portletId) { return StringUtil.contains(getModeEditDefaults(), portletId); } @Override public boolean hasModeEditGuestPortletId(String portletId) { return StringUtil.contains(getModeEditGuest(), portletId); } @Override public boolean hasModeEditPortletId(String portletId) { return StringUtil.contains(getModeEdit(), portletId); } @Override public boolean hasModeHelpPortletId(String portletId) { return StringUtil.contains(getModeHelp(), portletId); } @Override public boolean hasModePreviewPortletId(String portletId) { return StringUtil.contains(getModePreview(), portletId); } @Override public boolean hasModePrintPortletId(String portletId) { return StringUtil.contains(getModePrint(), portletId); } @Override public boolean hasModeViewPortletId(String portletId) { if (hasModeAboutPortletId(portletId) || hasModeConfigPortletId(portletId) || hasModeEditPortletId(portletId) || hasModeEditDefaultsPortletId(portletId) || hasModeEditGuestPortletId(portletId) || hasModeHelpPortletId(portletId) || hasModePreviewPortletId(portletId) || hasModePrintPortletId(portletId)) { return false; } else { return true; } } @Override public boolean hasPortletId(String portletId) { return hasPortletId(portletId, false); } @Override public boolean hasPortletId(String portletId, boolean strict) { List<String> columns = getColumns(); for (String columnId : columns) { if (hasNonstaticPortletId(columnId, portletId)) { return true; } if (hasStaticPortletId(columnId, portletId)) { return true; } } Layout layout = getLayout(); if (layout.isTypeControlPanel()) { return false; } if (isCustomizable() && isCustomizedView()) { LayoutTypePortletImpl defaultLayoutTypePortletImpl = getDefaultLayoutTypePortletImpl(); if (defaultLayoutTypePortletImpl.hasNonstaticPortletId(portletId)) { return false; } } if (!strict && ((PortletPreferencesLocalServiceUtil.getPortletPreferencesCount( PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid(), portletId) > 0) || (PortletPreferencesLocalServiceUtil.getPortletPreferencesCount( PortletKeys.PREFS_OWNER_TYPE_USER, layout.getPlid(), portletId) > 0))) { return true; } return false; } @Override public boolean hasStateMax() { String[] stateMax = StringUtil.split(getStateMax()); if (stateMax.length > 0) { return true; } else { return false; } } @Override public boolean hasStateMaxPortletId(String portletId) { if (StringUtil.contains(getStateMax(), portletId)) { return true; } else { return false; } } @Override public boolean hasStateMin() { String[] stateMin = StringUtil.split(getStateMin()); if (stateMin.length > 0) { return true; } else { return false; } } @Override public boolean hasStateMinPortletId(String portletId) { if (StringUtil.contains(getStateMin(), portletId)) { return true; } else { return false; } } @Override public boolean hasStateNormalPortletId(String portletId) { if (hasStateMaxPortletId(portletId) || hasStateMinPortletId(portletId)) { return false; } else { return true; } } @Override public boolean hasUpdatePermission() { return _updatePermission; } @Override public boolean isCacheable() { List<Portlet> portlets = new ArrayList<>(); for (String columnId : getColumns()) { List<Portlet> columnPortlets = getAllPortlets(columnId); for (Portlet portlet : columnPortlets) { Portlet rootPortlet = portlet.getRootPortlet(); if (!rootPortlet.isLayoutCacheable()) { return false; } } portlets.addAll(columnPortlets); } List<Portlet> staticPortlets = getStaticPortlets( PropsKeys.LAYOUT_STATIC_PORTLETS_ALL); for (Portlet portlet : staticPortlets) { Portlet rootPortlet = portlet.getRootPortlet(); if (!rootPortlet.isLayoutCacheable()) { return false; } } List<Portlet> embeddedPortlets = getEmbeddedPortlets(); for (Portlet portlet : embeddedPortlets) { Portlet rootPortlet = portlet.getRootPortlet(); if (!rootPortlet.isLayoutCacheable()) { return false; } } return true; } @Override public boolean isColumnCustomizable(String columnId) { String customizableString = getTypeSettingsProperty( CustomizedPages.namespaceColumnId(columnId)); boolean customizable = GetterUtil.getBoolean(customizableString); if (customizable) { if (isLayoutSetPrototype()) { return false; } return true; } if (hasUserPreferences()) { String columnValue = _portalPreferences.getValue( CustomizedPages.namespacePlid(getPlid()), columnId, StringPool.NULL); if (!Objects.equals(columnValue, StringPool.NULL)) { setUserPreference(columnId, null); } } return false; } @Override public boolean isColumnDisabled(String columnId) { if ((isCustomizedView() && !isColumnCustomizable(columnId)) || (!isCustomizedView() && !hasUpdatePermission())) { return true; } return false; } @Override public boolean isCustomizable() { for (String columnId : getColumns()) { if (isColumnCustomizable(columnId)) { return true; } } return false; } @Override public boolean isCustomizedView() { return _customizedView; } @Override public boolean isDefaultUpdated() { if (!isCustomizedView() || !hasUserPreferences()) { return false; } String preferencesModifiedDateString = _portalPreferences.getValue( CustomizedPages.namespacePlid(getPlid()), _MODIFIED_DATE, _NULL_DATE); DateFormat dateFormat = DateFormatFactoryUtil.getSimpleDateFormat( PropsValues.INDEX_DATE_FORMAT_PATTERN); try { Date preferencesModifiedDate = dateFormat.parse( preferencesModifiedDateString); Layout layout = getLayout(); String propertiesModifiedDateString = layout.getTypeSettingsProperty(_MODIFIED_DATE, _NULL_DATE); Date propertiesModifiedDate = dateFormat.parse( propertiesModifiedDateString); return propertiesModifiedDate.after(preferencesModifiedDate); } catch (Exception e) { _log.error(e, e); } return false; } @Override public boolean isPortletCustomizable(String portletId) { return isColumnCustomizable(getColumn(portletId)); } @Override public boolean isPortletEmbedded(String portletId) { Layout layout = getLayout(); return layout.isPortletEmbedded(portletId, layout.getGroupId()); } @Override public void movePortletId( long userId, String portletId, String columnId, int columnPos) { if (!hasPortletId(portletId)) { return; } _enablePortletLayoutListener = false; try { removePortletId(userId, portletId, false); addPortletId(userId, portletId, columnId, columnPos, false, true); } finally { _enablePortletLayoutListener = true; } Layout layout = getLayout(); try { Portlet portlet = PortletLocalServiceUtil.getPortletById( layout.getCompanyId(), portletId); if (portlet != null) { PortletLayoutListener portletLayoutListener = portlet.getPortletLayoutListenerInstance(); if (portletLayoutListener != null) { portletLayoutListener.onMoveInLayout( portletId, layout.getPlid()); } } } catch (Exception e) { _log.error("Unable to fire portlet layout listener event", e); } } @Override public void removeCustomization(UnicodeProperties typeSettingsProperties) { for (String columnId : getColumns()) { if (!isColumnCustomizable(columnId)) { continue; } if (GetterUtil.getBoolean( getTypeSettingsProperty( CustomizedPages.namespaceColumnId(columnId)))) { typeSettingsProperties.remove( CustomizedPages.namespaceColumnId(columnId)); } } } @Override public void removeModeAboutPortletId(String portletId) { setModeAbout(StringUtil.removeFromList(getModeAbout(), portletId)); } @Override public void removeModeConfigPortletId(String portletId) { setModeConfig(StringUtil.removeFromList(getModeConfig(), portletId)); } @Override public void removeModeEditDefaultsPortletId(String portletId) { setModeEditDefaults( StringUtil.removeFromList(getModeEditDefaults(), portletId)); } @Override public void removeModeEditGuestPortletId(String portletId) { setModeEditGuest( StringUtil.removeFromList(getModeEditGuest(), portletId)); } @Override public void removeModeEditPortletId(String portletId) { setModeEdit(StringUtil.removeFromList(getModeEdit(), portletId)); } @Override public void removeModeHelpPortletId(String portletId) { setModeHelp(StringUtil.removeFromList(getModeHelp(), portletId)); } @Override public void removeModePreviewPortletId(String portletId) { setModePreview(StringUtil.removeFromList(getModePreview(), portletId)); } @Override public void removeModePrintPortletId(String portletId) { setModePrint(StringUtil.removeFromList(getModePrint(), portletId)); } @Override public void removeModesPortletId(String portletId) { removeModeAboutPortletId(portletId); removeModeConfigPortletId(portletId); removeModeEditPortletId(portletId); removeModeEditDefaultsPortletId(portletId); removeModeEditGuestPortletId(portletId); removeModeHelpPortletId(portletId); removeModePreviewPortletId(portletId); removeModePrintPortletId(portletId); } @Override public void removeNestedColumns(String portletNamespace) { UnicodeProperties typeSettingsProperties = getTypeSettingsProperties(); UnicodeProperties newTypeSettingsProperties = new UnicodeProperties(); for (Map.Entry<String, String> entry : typeSettingsProperties.entrySet()) { String key = entry.getKey(); if (!key.startsWith(portletNamespace)) { newTypeSettingsProperties.setProperty(key, entry.getValue()); } } Layout layout = getLayout(); layout.setTypeSettingsProperties(newTypeSettingsProperties); String nestedColumnIds = GetterUtil.getString( getTypeSettingsProperty( LayoutTypePortletConstants.NESTED_COLUMN_IDS)); String[] nestedColumnIdsArray = ArrayUtil.removeByPrefix( StringUtil.split(nestedColumnIds), portletNamespace); setTypeSettingsProperty( LayoutTypePortletConstants.NESTED_COLUMN_IDS, StringUtil.merge(nestedColumnIdsArray)); } @Override public void removePortletId(long userId, String portletId) { removePortletId(userId, portletId, true); } @Override public void removePortletId( long userId, String portletId, boolean cleanUp) { try { Portlet portlet = PortletLocalServiceUtil.getPortletById( getCompanyId(), portletId); if (portlet == null) { _log.error( "Portlet " + portletId + " cannot be removed because it is not registered"); return; } PermissionChecker permissionChecker = PermissionThreadLocal.getPermissionChecker(); if (!LayoutPermissionUtil.contains( permissionChecker, getLayout(), ActionKeys.UPDATE) && !isCustomizable()) { return; } } catch (Exception e) { _log.error(e, e); return; } List<String> columns = getColumns(); for (int i = 0; i < columns.size(); i++) { String columnId = columns.get(i); if (isCustomizable() && isColumnDisabled(columnId)) { continue; } String columnValue = null; if (hasUserPreferences()) { columnValue = getUserPreference(columnId); } else { columnValue = getTypeSettingsProperty(columnId); } columnValue = StringUtil.removeFromList(columnValue, portletId); if (StringUtil.endsWith(columnValue, StringPool.COMMA)) { columnValue = columnValue.substring( 0, columnValue.length() - 1); } if (hasUserPreferences()) { setUserPreference(columnId, columnValue); } else { setTypeSettingsProperty(columnId, columnValue); } } if (cleanUp) { try { onRemoveFromLayout(new String[] {portletId}); } catch (Exception e) { _log.error(e, e); } } } @Override public void removeStateMaxPortletId(String portletId) { setStateMax(StringUtil.removeFromList(getStateMax(), portletId)); } @Override public void removeStateMinPortletId(String portletId) { setStateMin(StringUtil.removeFromList(getStateMin(), portletId)); } @Override public void removeStatesPortletId(String portletId) { removeStateMaxPortletId(portletId); removeStateMinPortletId(portletId); } @Override public void reorganizePortlets( List<String> newColumns, List<String> oldColumns) { String lastNewColumnId = newColumns.get(newColumns.size() - 1); String lastNewColumnValue = getTypeSettingsProperty(lastNewColumnId); for (String oldColumnId : oldColumns) { if (!newColumns.contains(oldColumnId)) { String oldColumnValue = getTypeSettingsProperties().remove( oldColumnId); String[] portletIds = StringUtil.split(oldColumnValue); for (String portletId : portletIds) { lastNewColumnValue = StringUtil.add( lastNewColumnValue, portletId); } } } setTypeSettingsProperty(lastNewColumnId, lastNewColumnValue); } @Override public void resetModes() { setModeAbout(StringPool.BLANK); setModeConfig(StringPool.BLANK); setModeEdit(StringPool.BLANK); setModeEditDefaults(StringPool.BLANK); setModeEditGuest(StringPool.BLANK); setModeHelp(StringPool.BLANK); setModePreview(StringPool.BLANK); setModePrint(StringPool.BLANK); } @Override public void resetStates() { setStateMax(StringPool.BLANK); setStateMin(StringPool.BLANK); } @Override public void resetUserPreferences() { if (!hasUserPreferences()) { return; } long plid = getPlid(); Set<String> customPortletIds = new HashSet<>(); for (String columnId : getColumns()) { String value = _portalPreferences.getValue( CustomizedPages.namespacePlid(plid), columnId); for (String customPortletId : StringUtil.split(value)) { customPortletIds.add(customPortletId); } } try { onRemoveFromLayout( customPortletIds.toArray(new String[customPortletIds.size()])); } catch (Exception e) { _log.error(e, e); } _portalPreferences.resetValues(CustomizedPages.namespacePlid(plid)); _portalPreferences.setValue( CustomizedPages.namespacePlid(plid), _MODIFIED_DATE, _dateFormat.format(new Date())); } @Override public void setCustomizedView(boolean customizedView) { _customizedView = customizedView; } @Override public void setLayoutTemplateId(long userId, String newLayoutTemplateId) { setLayoutTemplateId(userId, newLayoutTemplateId, true); } @Override public void setLayoutTemplateId( long userId, String newLayoutTemplateId, boolean checkPermission) { if (checkPermission && !PluginSettingLocalServiceUtil.hasPermission( userId, newLayoutTemplateId, Plugin.TYPE_LAYOUT_TEMPLATE)) { return; } LayoutTemplate oldLayoutTemplate = getLayoutTemplate(); String themeId = getThemeId(); LayoutTemplate newLayoutTemplate = LayoutTemplateLocalServiceUtil.getLayoutTemplate( newLayoutTemplateId, false, themeId); if (newLayoutTemplate == null) { if (_log.isWarnEnabled()) { _log.warn( "Unable to find layout template " + newLayoutTemplateId); } return; } setTypeSettingsProperty( LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID, newLayoutTemplateId); List<String> oldColumns = oldLayoutTemplate.getColumns(); List<String> newColumns = newLayoutTemplate.getColumns(); reorganizePortlets(newColumns, oldColumns); } @Override public void setModeAbout(String modeAbout) { setTypeSettingsProperty( LayoutTypePortletConstants.MODE_ABOUT, modeAbout); } @Override public void setModeConfig(String modeConfig) { setTypeSettingsProperty( LayoutTypePortletConstants.MODE_CONFIG, modeConfig); } @Override public void setModeEdit(String modeEdit) { setTypeSettingsProperty(LayoutTypePortletConstants.MODE_EDIT, modeEdit); } @Override public void setModeEditDefaults(String modeEditDefaults) { setTypeSettingsProperty( LayoutTypePortletConstants.MODE_EDIT_DEFAULTS, modeEditDefaults); } @Override public void setModeEditGuest(String modeEditGuest) { setTypeSettingsProperty( LayoutTypePortletConstants.MODE_EDIT_GUEST, modeEditGuest); } @Override public void setModeHelp(String modeHelp) { setTypeSettingsProperty(LayoutTypePortletConstants.MODE_HELP, modeHelp); } @Override public void setModePreview(String modePreview) { setTypeSettingsProperty( LayoutTypePortletConstants.MODE_PREVIEW, modePreview); } @Override public void setModePrint(String modePrint) { setTypeSettingsProperty( LayoutTypePortletConstants.MODE_PRINT, modePrint); } @Override public void setPortalPreferences(PortalPreferences portalPreferences) { _portalPreferences = portalPreferences; } @Override public void setStateMax(String stateMax) { setTypeSettingsProperty(LayoutTypePortletConstants.STATE_MAX, stateMax); } @Override public void setStateMin(String stateMin) { setTypeSettingsProperty(LayoutTypePortletConstants.STATE_MIN, stateMin); } @Override public void setUpdatePermission(boolean updatePermission) { _updatePermission = updatePermission; } protected void addNestedColumn(String columnId) { String nestedColumnIds = getTypeSettingsProperty( LayoutTypePortletConstants.NESTED_COLUMN_IDS, StringPool.BLANK); if (!nestedColumnIds.contains(columnId)) { nestedColumnIds = StringUtil.add(nestedColumnIds, columnId); setTypeSettingsProperty( LayoutTypePortletConstants.NESTED_COLUMN_IDS, nestedColumnIds); } } protected String addPortletId( long userId, String portletId, String columnId, int columnPos, boolean checkPermission, boolean strictHasPortlet) { portletId = JS.getSafeName(portletId); Layout layout = getLayout(); Portlet portlet = null; try { portlet = PortletLocalServiceUtil.getPortletById( layout.getCompanyId(), portletId); if (portlet == null) { if (_log.isWarnEnabled()) { _log.warn( "Portlet " + portletId + " cannot be added because it is not registered"); } return null; } PermissionChecker permissionChecker = PermissionThreadLocal.getPermissionChecker(); if (checkPermission && !PortletPermissionUtil.contains( permissionChecker, layout, portlet, ActionKeys.ADD_TO_PAGE)) { return null; } } catch (Exception e) { _log.error(e, e); } if (portlet.isSystem()) { return null; } if (portlet.isInstanceable() && !PortletConstants.hasInstanceId(portletId)) { portletId = PortletConstants.assemblePortletId( portletId, PortletConstants.generateInstanceId()); } if (hasPortletId(portletId, strictHasPortlet)) { return null; } if (columnId == null) { LayoutTemplate layoutTemplate = getLayoutTemplate(); List<String> columns = layoutTemplate.getColumns(); if (!columns.isEmpty()) { columnId = columns.get(0); } } if (columnId == null) { return null; } if (isCustomizable()) { if (isColumnDisabled(columnId)) { return null; } if (hasUserPreferences()) { portletId = PortletConstants.assemblePortletId( portletId, userId); } } String columnValue = StringPool.BLANK; if (hasUserPreferences()) { columnValue = getUserPreference(columnId); } else { columnValue = getTypeSettingsProperty(columnId); } if ((columnValue == null) && columnId.startsWith(_NESTED_PORTLETS_NAMESPACE)) { addNestedColumn(columnId); } if (columnPos >= 0) { List<String> portletIds = ListUtil.fromArray( StringUtil.split(columnValue)); if (columnPos <= portletIds.size()) { portletIds.add(columnPos, portletId); } else { portletIds.add(portletId); } columnValue = StringUtil.merge(portletIds); } else { columnValue = StringUtil.add(columnValue, portletId); } if (hasUserPreferences()) { setUserPreference(columnId, columnValue); } else { setTypeSettingsProperty(columnId, columnValue); } try { if (_enablePortletLayoutListener && !portlet.isUndeployedPortlet()) { PortletLayoutListener portletLayoutListener = portlet.getPortletLayoutListenerInstance(); if (portletLayoutListener != null) { portletLayoutListener.onAddToLayout( portletId, layout.getPlid()); } } } catch (Exception e) { _log.error("Unable to fire portlet layout listener event", e); } return portletId; } protected void copyPreferences( long userId, String sourcePortletId, String targetPortletId) { Layout layout = getLayout(); try { PortletPreferencesIds portletPreferencesIds = PortletPreferencesFactoryUtil.getPortletPreferencesIds( layout.getGroupId(), 0, layout, sourcePortletId, false); javax.portlet.PortletPreferences sourcePortletPreferences = PortletPreferencesLocalServiceUtil.getStrictPreferences( portletPreferencesIds); portletPreferencesIds = PortletPreferencesFactoryUtil.getPortletPreferencesIds( layout.getGroupId(), userId, layout, targetPortletId, false); PortletPreferencesLocalServiceUtil.updatePreferences( portletPreferencesIds.getOwnerId(), portletPreferencesIds.getOwnerType(), portletPreferencesIds.getPlid(), portletPreferencesIds.getPortletId(), sourcePortletPreferences); } catch (Exception e) { } } protected void copyResourcePermissions( String sourcePortletId, String targetPortletId) { Layout layout = getLayout(); Portlet portlet = PortletLocalServiceUtil.getPortletById( getCompanyId(), sourcePortletId); String sourcePortletPrimaryKey = PortletPermissionUtil.getPrimaryKey( layout.getPlid(), sourcePortletId); List<ResourcePermission> resourcePermissions = ResourcePermissionLocalServiceUtil.getResourcePermissions( portlet.getCompanyId(), portlet.getPortletName(), PortletKeys.PREFS_OWNER_TYPE_USER, sourcePortletPrimaryKey); for (ResourcePermission resourcePermission : resourcePermissions) { String targetPortletPrimaryKey = PortletPermissionUtil.getPrimaryKey( layout.getPlid(), targetPortletId); resourcePermission.setResourcePermissionId( CounterLocalServiceUtil.increment()); resourcePermission.setPrimKey(targetPortletPrimaryKey); ResourcePermissionLocalServiceUtil.addResourcePermission( resourcePermission); } } protected String getColumn(String portletId) { String portletIdColumnId = StringPool.BLANK; List<String> columnIds = getColumns(); for (String columnId : columnIds) { String columnValue = getColumnValue(columnId); String[] portletIds = StringUtil.split(columnValue); for (String columnPortletId : portletIds) { if (columnPortletId.equals(portletId)) { return columnId; } if (Validator.isNull(portletIdColumnId) && PortletConstants.hasIdenticalRootPortletId( columnPortletId, portletId)) { portletIdColumnId = columnId; } } } return portletIdColumnId; } protected List<String> getColumns() { List<String> columns = new ArrayList<>(); Layout layout = getLayout(); if (layout.isTypePortlet()) { LayoutTemplate layoutTemplate = getLayoutTemplate(); columns.addAll(layoutTemplate.getColumns()); columns.addAll(getNestedColumns()); } else if (layout.isTypePanel()) { columns.add("panelSelectedPortlets"); } return columns; } protected String getColumnValue(String columnId) { if (hasUserPreferences() && isCustomizable() && !isColumnDisabled(columnId)) { return getUserPreference(columnId); } return getTypeSettingsProperty(columnId); } protected long getCompanyId() { Layout layout = getLayout(); return layout.getCompanyId(); } protected LayoutTypePortletImpl getDefaultLayoutTypePortletImpl() { if (!isCustomizedView()) { return this; } LayoutTypePortletImpl defaultLayoutTypePortletImpl = (LayoutTypePortletImpl)LayoutTypePortletFactoryUtil.create( getLayout()); defaultLayoutTypePortletImpl._layoutSetPrototypeLayout = _layoutSetPrototypeLayout; defaultLayoutTypePortletImpl._updatePermission = _updatePermission; return defaultLayoutTypePortletImpl; } protected List<String> getNestedColumns() { String nestedColumnIds = getTypeSettingsProperty( LayoutTypePortletConstants.NESTED_COLUMN_IDS); return ListUtil.fromArray(StringUtil.split(nestedColumnIds)); } protected long getPlid() { Layout layout = getLayout(); return layout.getPlid(); } protected String[] getStaticPortletIds(String position) { Layout layout = getLayout(); String selector1 = StringPool.BLANK; Group group = _getGroup(); if (group == null) { _log.error("Unable to get group " + layout.getGroupId()); return new String[0]; } if (group.isUser()) { selector1 = LayoutTypePortletConstants.STATIC_PORTLET_USER_SELECTOR; } else if (group.isOrganization()) { selector1 = LayoutTypePortletConstants.STATIC_PORTLET_ORGANIZATION_SELECTOR; } else if (group.isRegularSite()) { selector1 = LayoutTypePortletConstants.STATIC_PORTLET_REGULAR_SITE_SELECTOR; } String selector2 = layout.getFriendlyURL(); String[] portletIds = PropsUtil.getArray( position, new Filter(selector1, selector2)); for (int i = 0; i < portletIds.length; i++) { portletIds[i] = JS.getSafeName(portletIds[i]); } return portletIds; } protected List<Portlet> getStaticPortlets(String position) { String[] portletIds = getStaticPortletIds(position); List<Portlet> portlets = new ArrayList<>(); for (String portletId : portletIds) { if (Validator.isNull(portletId) || hasNonstaticPortletId(portletId)) { continue; } Portlet portlet = PortletLocalServiceUtil.getPortletById( getCompanyId(), portletId); if (portlet != null) { Portlet staticPortlet = 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 { staticPortlet = new PortletWrapper(portlet) { @Override public boolean getStatic() { return _staticPortlet; } @Override public boolean getStaticStart() { return _staticPortletStart; } @Override public boolean isStatic() { return _staticPortlet; } @Override public boolean isStaticStart() { return _staticPortletStart; } @Override public void setStatic(boolean staticPortlet) { _staticPortlet = staticPortlet; } @Override public void setStaticStart(boolean staticPortletStart) { _staticPortletStart = staticPortletStart; } private boolean _staticPortlet; private boolean _staticPortletStart; }; } staticPortlet.setStatic(true); if (position.startsWith("layout.static.portlets.start")) { staticPortlet.setStaticStart(true); } portlets.add(staticPortlet); } } return portlets; } protected String getThemeId() { try { Layout layout = getLayout(); LayoutSet layoutSet = layout.getLayoutSet(); return layoutSet.getThemeId(); } catch (Exception e) { _log.error(e, e); } return null; } protected String getUserPreference(String key) { String value = StringPool.BLANK; if (!hasUserPreferences()) { return value; } value = _portalPreferences.getValue( CustomizedPages.namespacePlid(getPlid()), key, StringPool.NULL); if (!value.equals(StringPool.NULL)) { return value; } value = getTypeSettingsProperty(key); if (Validator.isNull(value)) { return value; } List<String> newPortletIds = new ArrayList<>(); PermissionChecker permissionChecker = PermissionThreadLocal.getPermissionChecker(); String[] portletIds = StringUtil.split(value); for (String portletId : portletIds) { try { if (!PortletPermissionUtil.contains( permissionChecker, getLayout(), portletId, ActionKeys.VIEW, true)) { continue; } String rootPortletId = PortletConstants.getRootPortletId( portletId); if (!PortletPermissionUtil.contains( permissionChecker, rootPortletId, ActionKeys.ADD_TO_PAGE)) { continue; } } catch (Exception e) { _log.error(e, e); } String newPortletId = null; boolean preferencesUniquePerLayout = false; try { Portlet portlet = PortletLocalServiceUtil.getPortletById( getCompanyId(), portletId); preferencesUniquePerLayout = portlet.isPreferencesUniquePerLayout(); } catch (SystemException se) { _log.error(se, se); } if (PortletConstants.hasInstanceId(portletId) || preferencesUniquePerLayout) { String instanceId = null; if (PortletConstants.hasInstanceId(portletId)) { instanceId = PortletConstants.generateInstanceId(); } newPortletId = PortletConstants.assemblePortletId( portletId, _portalPreferences.getUserId(), instanceId); copyPreferences( _portalPreferences.getUserId(), portletId, newPortletId); copyResourcePermissions(portletId, newPortletId); } else { newPortletId = portletId; } newPortletIds.add(newPortletId); } value = StringUtil.merge(newPortletIds); setUserPreference(key, value); return value; } protected boolean hasNonstaticPortletId(String portletId) { LayoutTemplate layoutTemplate = getLayoutTemplate(); List<String> columns = layoutTemplate.getColumns(); for (int i = 0; i < columns.size(); i++) { String columnId = columns.get(i); if (hasNonstaticPortletId(columnId, portletId)) { return true; } } return false; } protected boolean hasNonstaticPortletId(String columnId, String portletId) { String columnValue = getColumnValue(columnId); String[] columnValues = StringUtil.split(columnValue); for (String nonstaticPortletId : columnValues) { if (nonstaticPortletId.equals(portletId) || PortletConstants.getRootPortletId( nonstaticPortletId).equals(portletId)) { return true; } } return false; } protected boolean hasStaticPortletId(String columnId, String portletId) { String[] staticPortletIdsStart = getStaticPortletIds( PropsKeys.LAYOUT_STATIC_PORTLETS_START + columnId); String[] staticPortletIdsEnd = getStaticPortletIds( PropsKeys.LAYOUT_STATIC_PORTLETS_END + columnId); for (String staticPortletId : staticPortletIdsStart) { if (staticPortletId.equals(portletId) || PortletConstants.getRootPortletId( staticPortletId).equals(portletId)) { return true; } } for (String staticPortletId : staticPortletIdsEnd) { if (staticPortletId.equals(portletId) || PortletConstants.getRootPortletId( staticPortletId).equals(portletId)) { return true; } } return false; } protected boolean hasUserPreferences() { if (_portalPreferences != null) { return true; } return false; } protected boolean isLayoutSetPrototype() { try { Group group = _getGroup(); return group.isLayoutSetPrototype(); } catch (Exception e) { _log.error(e, e); } return false; } protected void onRemoveFromLayout(String[] portletIds) { Set<String> portletIdList = new HashSet<>(); for (String portletId : portletIds) { removeModesPortletId(portletId); removeStatesPortletId(portletId); portletIdList.add(portletId); String rootPortletId = PortletConstants.getRootPortletId(portletId); if (rootPortletId.equals(PortletKeys.NESTED_PORTLETS)) { String portletNamespace = PortalUtil.getPortletNamespace( portletId); UnicodeProperties typeSettingsProperties = getTypeSettingsProperties(); for (Map.Entry<String, String> entry : typeSettingsProperties.entrySet()) { String key = entry.getKey(); if (!key.startsWith(portletNamespace)) { continue; } String nestedPortletIds = entry.getValue(); for (String nestedPortletId : StringUtil.split(nestedPortletIds)) { removeModesPortletId(nestedPortletId); removeStatesPortletId(nestedPortletId); portletIdList.add(nestedPortletId); } } removeNestedColumns(portletNamespace); } Portlet portlet = PortletLocalServiceUtil.getPortletById(portletId); if (portlet == null) { continue; } PortletLayoutListener portletLayoutListener = portlet.getPortletLayoutListenerInstance(); if (portletLayoutListener == null) { continue; } portletLayoutListener.updatePropertiesOnRemoveFromLayout( portletId, getTypeSettingsProperties()); } try { PortletLocalServiceUtil.deletePortlets( getCompanyId(), portletIdList.toArray(new String[portletIdList.size()]), getPlid()); } catch (PortalException pe) { _log.error(pe, pe); } } protected void setUserPreference(String key, String value) { _portalPreferences.setValue( CustomizedPages.namespacePlid(getPlid()), key, value); _portalPreferences.setValue( CustomizedPages.namespacePlid(getPlid()), _MODIFIED_DATE, _dateFormat.format(new Date())); } private Group _getGroup() { if (_group == null) { Layout layout = getLayout(); _group = layout.getGroup(); } return _group; } private static final String _MODIFIED_DATE = "modifiedDate"; private static final String _NESTED_PORTLETS_NAMESPACE = PortalUtil.getPortletNamespace(PortletKeys.NESTED_PORTLETS); private static final String _NULL_DATE = "00000000000000"; private static final Log _log = LogFactoryUtil.getLog( LayoutTypePortletImpl.class); private static final Layout _nullLayout = new LayoutImpl(); private boolean _customizedView; private final Format _dateFormat = FastDateFormatFactoryUtil.getSimpleDateFormat( PropsValues.INDEX_DATE_FORMAT_PATTERN); private boolean _enablePortletLayoutListener = true; private Group _group; private Layout _layoutSetPrototypeLayout; private PortalPreferences _portalPreferences; private boolean _updatePermission; }