/**
* 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.service.impl;
import com.liferay.exportimport.kernel.staging.MergeLayoutPrototypesThreadLocal;
import com.liferay.exportimport.kernel.staging.StagingUtil;
import com.liferay.portal.kernel.exception.NoSuchLayoutRevisionException;
import com.liferay.portal.kernel.exception.NoSuchPortletPreferencesException;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.Layout;
import com.liferay.portal.kernel.model.LayoutConstants;
import com.liferay.portal.kernel.model.LayoutRevision;
import com.liferay.portal.kernel.model.LayoutRevisionConstants;
import com.liferay.portal.kernel.model.LayoutSetBranch;
import com.liferay.portal.kernel.model.PortletPreferences;
import com.liferay.portal.kernel.model.User;
import com.liferay.portal.kernel.service.ServiceContext;
import com.liferay.portal.kernel.util.AutoResetThreadLocal;
import com.liferay.portal.kernel.util.OrderByComparator;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.comparator.LayoutRevisionCreateDateComparator;
import com.liferay.portal.kernel.workflow.WorkflowConstants;
import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
import com.liferay.portal.service.base.LayoutRevisionLocalServiceBaseImpl;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @author Raymond Augé
* @author Brian Wing Shun Chan
*/
public class LayoutRevisionLocalServiceImpl
extends LayoutRevisionLocalServiceBaseImpl {
@Override
public LayoutRevision addLayoutRevision(
long userId, long layoutSetBranchId, long layoutBranchId,
long parentLayoutRevisionId, boolean head, long plid,
long portletPreferencesPlid, boolean privateLayout, String name,
String title, String description, String keywords, String robots,
String typeSettings, boolean iconImage, long iconImageId,
String themeId, String colorSchemeId, String css,
ServiceContext serviceContext)
throws PortalException {
// Layout revision
User user = userPersistence.findByPrimaryKey(userId);
LayoutSetBranch layoutSetBranch =
layoutSetBranchPersistence.findByPrimaryKey(layoutSetBranchId);
parentLayoutRevisionId = getParentLayoutRevisionId(
layoutSetBranchId, parentLayoutRevisionId, plid);
Date now = new Date();
long layoutRevisionId = counterLocalService.increment();
LayoutRevision layoutRevision = layoutRevisionPersistence.create(
layoutRevisionId);
layoutRevision.setGroupId(layoutSetBranch.getGroupId());
layoutRevision.setCompanyId(user.getCompanyId());
layoutRevision.setUserId(user.getUserId());
layoutRevision.setUserName(user.getFullName());
layoutRevision.setLayoutSetBranchId(layoutSetBranchId);
layoutRevision.setLayoutBranchId(layoutBranchId);
layoutRevision.setParentLayoutRevisionId(parentLayoutRevisionId);
layoutRevision.setHead(head);
layoutRevision.setPlid(plid);
layoutRevision.setPrivateLayout(privateLayout);
layoutRevision.setName(name);
layoutRevision.setTitle(title);
layoutRevision.setDescription(description);
layoutRevision.setKeywords(keywords);
layoutRevision.setRobots(robots);
layoutRevision.setTypeSettings(typeSettings);
layoutRevision.setIconImageId(iconImageId);
layoutRevision.setThemeId(themeId);
layoutRevision.setColorSchemeId(colorSchemeId);
layoutRevision.setCss(css);
layoutRevision.setStatus(WorkflowConstants.STATUS_DRAFT);
layoutRevision.setStatusDate(serviceContext.getModifiedDate(now));
layoutRevisionPersistence.update(layoutRevision);
_layoutRevisionId.set(layoutRevision.getLayoutRevisionId());
// Portlet preferences
if (portletPreferencesPlid == LayoutConstants.DEFAULT_PLID) {
portletPreferencesPlid = plid;
}
copyPortletPreferences(layoutRevision, portletPreferencesPlid);
boolean major = ParamUtil.getBoolean(serviceContext, "major");
if (major || !isWorkflowEnabled(plid)) {
updateMajor(layoutRevision);
}
// Workflow
if (isWorkflowEnabled(plid)) {
WorkflowHandlerRegistryUtil.startWorkflowInstance(
user.getCompanyId(), layoutRevision.getGroupId(),
user.getUserId(), LayoutRevision.class.getName(),
layoutRevision.getLayoutRevisionId(), layoutRevision,
serviceContext);
}
else {
updateStatus(
userId, layoutRevisionId, WorkflowConstants.STATUS_APPROVED,
serviceContext);
}
StagingUtil.setRecentLayoutRevisionId(
user, layoutSetBranchId, plid,
layoutRevision.getLayoutRevisionId());
return layoutRevision;
}
@Override
public void deleteLayoutLayoutRevisions(long plid) throws PortalException {
for (LayoutRevision layoutRevision : getLayoutRevisions(plid)) {
layoutRevisionLocalService.deleteLayoutRevision(layoutRevision);
}
}
@Override
public LayoutRevision deleteLayoutRevision(LayoutRevision layoutRevision)
throws PortalException {
if (layoutRevision.hasChildren()) {
for (LayoutRevision curLayoutRevision :
layoutRevision.getChildren()) {
curLayoutRevision.setParentLayoutRevisionId(
layoutRevision.getParentLayoutRevisionId());
layoutRevisionPersistence.update(curLayoutRevision);
}
}
List<PortletPreferences> portletPreferencesList =
portletPreferencesLocalService.getPortletPreferencesByPlid(
layoutRevision.getLayoutRevisionId());
for (PortletPreferences portletPreferences : portletPreferencesList) {
try {
portletPreferencesLocalService.deletePortletPreferences(
portletPreferences.getPortletPreferencesId());
}
catch (NoSuchPortletPreferencesException nsppe) {
// LPS-52675
if (_log.isDebugEnabled()) {
_log.debug(nsppe, nsppe);
}
}
}
recentLayoutRevisionLocalService.deleteRecentLayoutRevisions(
layoutRevision.getLayoutRevisionId());
workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
layoutRevision.getCompanyId(), layoutRevision.getGroupId(),
LayoutRevision.class.getName(),
layoutRevision.getLayoutRevisionId());
return layoutRevisionPersistence.remove(layoutRevision);
}
@Override
public LayoutRevision deleteLayoutRevision(long layoutRevisionId)
throws PortalException {
LayoutRevision layoutRevision =
layoutRevisionPersistence.findByPrimaryKey(layoutRevisionId);
return deleteLayoutRevision(layoutRevision);
}
@Override
public void deleteLayoutRevisions(long layoutSetBranchId, long plid)
throws PortalException {
for (LayoutRevision layoutRevision : getLayoutRevisions(
layoutSetBranchId, plid)) {
layoutRevisionLocalService.deleteLayoutRevision(layoutRevision);
}
}
@Override
public void deleteLayoutRevisions(
long layoutSetBranchId, long layoutBranchId, long plid)
throws PortalException {
List<LayoutRevision> layoutRevisions =
layoutRevisionPersistence.findByL_L_P(
layoutSetBranchId, layoutBranchId, plid);
for (LayoutRevision layoutRevision : layoutRevisions) {
layoutRevisionLocalService.deleteLayoutRevision(layoutRevision);
}
}
@Override
public void deleteLayoutSetBranchLayoutRevisions(long layoutSetBranchId)
throws PortalException {
List<LayoutRevision> layoutRevisions =
layoutRevisionPersistence.findByLayoutSetBranchId(
layoutSetBranchId);
for (LayoutRevision layoutRevision : layoutRevisions) {
layoutRevisionLocalService.deleteLayoutRevision(layoutRevision);
}
}
@Override
public LayoutRevision fetchLastLayoutRevision(long plid, boolean head) {
try {
return layoutRevisionPersistence.findByH_P_Last(
head, plid, new LayoutRevisionCreateDateComparator(true));
}
catch (NoSuchLayoutRevisionException nslre) {
// LPS-52675
if (_log.isDebugEnabled()) {
_log.debug(nslre, nslre);
}
return null;
}
}
@Override
public LayoutRevision fetchLatestLayoutRevision(
long layoutSetBranchId, long plid) {
return layoutRevisionPersistence.fetchByL_P_First(
layoutSetBranchId, plid,
new LayoutRevisionCreateDateComparator(false));
}
@Override
public LayoutRevision fetchLayoutRevision(
long layoutSetBranchId, boolean head, long plid) {
return layoutRevisionPersistence.fetchByL_H_P(
layoutSetBranchId, head, plid);
}
@Override
public LayoutRevision fetchLayoutRevision(
long layoutSetBranchId, long layoutBranchId, boolean head, long plid) {
return layoutRevisionPersistence.fetchByL_L_H_P(
layoutSetBranchId, layoutBranchId, head, plid);
}
@Override
public List<LayoutRevision> getChildLayoutRevisions(
long layoutSetBranchId, long parentLayoutRevisionId, long plid) {
return layoutRevisionPersistence.findByL_P_P(
layoutSetBranchId, parentLayoutRevisionId, plid);
}
@Override
public List<LayoutRevision> getChildLayoutRevisions(
long layoutSetBranchId, long parentLayoutRevision, long plid, int start,
int end, OrderByComparator<LayoutRevision> orderByComparator) {
return layoutRevisionPersistence.findByL_P_P(
layoutSetBranchId, parentLayoutRevision, plid, start, end,
orderByComparator);
}
@Override
public int getChildLayoutRevisionsCount(
long layoutSetBranchId, long parentLayoutRevision, long plid) {
return layoutRevisionPersistence.countByL_P_P(
layoutSetBranchId, parentLayoutRevision, plid);
}
@Override
public LayoutRevision getLayoutRevision(
long layoutSetBranchId, long plid, boolean head)
throws PortalException {
return layoutRevisionPersistence.findByL_H_P(
layoutSetBranchId, head, plid);
}
@Override
public LayoutRevision getLayoutRevision(
long layoutSetBranchId, long layoutBranchId, long plid)
throws PortalException {
List<LayoutRevision> layoutRevisions =
layoutRevisionPersistence.findByL_L_P(
layoutSetBranchId, layoutBranchId, plid, 0, 1,
new LayoutRevisionCreateDateComparator(false));
if (!layoutRevisions.isEmpty()) {
return layoutRevisions.get(0);
}
StringBundler sb = new StringBundler(7);
sb.append("{layoutSetBranchId=");
sb.append(layoutSetBranchId);
sb.append(", layoutBranchId=");
sb.append(layoutBranchId);
sb.append(", plid=");
sb.append(plid);
sb.append("}");
throw new NoSuchLayoutRevisionException(sb.toString());
}
@Override
public List<LayoutRevision> getLayoutRevisions(long plid) {
return layoutRevisionPersistence.findByPlid(plid);
}
@Override
public List<LayoutRevision> getLayoutRevisions(
long layoutSetBranchId, boolean head) {
return layoutRevisionPersistence.findByL_H(layoutSetBranchId, head);
}
@Override
public List<LayoutRevision> getLayoutRevisions(
long layoutSetBranchId, int status) {
return layoutRevisionPersistence.findByL_S(layoutSetBranchId, status);
}
@Override
public List<LayoutRevision> getLayoutRevisions(
long layoutSetBranchId, long plid) {
return layoutRevisionPersistence.findByL_P(layoutSetBranchId, plid);
}
@Override
public List<LayoutRevision> getLayoutRevisions(
long layoutSetBranchId, long plid, int status) {
return layoutRevisionPersistence.findByL_P_S(
layoutSetBranchId, plid, status);
}
@Override
public List<LayoutRevision> getLayoutRevisions(
long layoutSetBranchId, long plid, int start, int end,
OrderByComparator<LayoutRevision> orderByComparator) {
return layoutRevisionPersistence.findByL_P(
layoutSetBranchId, plid, start, end, orderByComparator);
}
@Override
public List<LayoutRevision> getLayoutRevisions(
long layoutSetBranchId, long layoutBranchId, long plid, int start,
int end, OrderByComparator<LayoutRevision> orderByComparator) {
return layoutRevisionPersistence.findByL_L_P(
layoutSetBranchId, layoutBranchId, plid, start, end,
orderByComparator);
}
@Override
public int getLayoutRevisionsCount(
long layoutSetBranchId, long layoutBranchId, long plid) {
return layoutRevisionPersistence.countByL_L_P(
layoutSetBranchId, layoutBranchId, plid);
}
@Override
public LayoutRevision updateLayoutRevision(
long userId, long layoutRevisionId, long layoutBranchId,
String name, String title, String description, String keywords,
String robots, String typeSettings, boolean iconImage,
long iconImageId, String themeId, String colorSchemeId, String css,
ServiceContext serviceContext)
throws PortalException {
// Layout revision
User user = userPersistence.findByPrimaryKey(userId);
LayoutRevision oldLayoutRevision =
layoutRevisionPersistence.findByPrimaryKey(layoutRevisionId);
Date now = new Date();
LayoutRevision layoutRevision = null;
int workflowAction = serviceContext.getWorkflowAction();
boolean revisionInProgress = ParamUtil.getBoolean(
serviceContext, "revisionInProgress");
if (!MergeLayoutPrototypesThreadLocal.isInProgress() &&
(workflowAction != WorkflowConstants.ACTION_PUBLISH) &&
(_layoutRevisionId.get() <= 0) && !revisionInProgress) {
long newLayoutRevisionId = counterLocalService.increment();
layoutRevision = layoutRevisionPersistence.create(
newLayoutRevisionId);
layoutRevision.setGroupId(oldLayoutRevision.getGroupId());
layoutRevision.setCompanyId(oldLayoutRevision.getCompanyId());
layoutRevision.setUserId(user.getUserId());
layoutRevision.setUserName(user.getFullName());
layoutRevision.setLayoutSetBranchId(
oldLayoutRevision.getLayoutSetBranchId());
layoutRevision.setParentLayoutRevisionId(
oldLayoutRevision.getLayoutRevisionId());
layoutRevision.setHead(false);
layoutRevision.setLayoutBranchId(layoutBranchId);
layoutRevision.setPlid(oldLayoutRevision.getPlid());
layoutRevision.setPrivateLayout(
oldLayoutRevision.isPrivateLayout());
layoutRevision.setName(name);
layoutRevision.setTitle(title);
layoutRevision.setDescription(description);
layoutRevision.setKeywords(keywords);
layoutRevision.setRobots(robots);
layoutRevision.setTypeSettings(typeSettings);
layoutRevision.setIconImageId(iconImageId);
layoutRevision.setThemeId(themeId);
layoutRevision.setColorSchemeId(colorSchemeId);
layoutRevision.setCss(css);
layoutRevision.setStatus(WorkflowConstants.STATUS_DRAFT);
layoutRevision.setStatusDate(serviceContext.getModifiedDate(now));
layoutRevisionPersistence.update(layoutRevision);
_layoutRevisionId.set(layoutRevision.getLayoutRevisionId());
// Portlet preferences
copyPortletPreferences(
layoutRevision, layoutRevision.getParentLayoutRevisionId());
StagingUtil.setRecentLayoutBranchId(
user, layoutRevision.getLayoutSetBranchId(),
layoutRevision.getPlid(), layoutRevision.getLayoutBranchId());
StagingUtil.setRecentLayoutRevisionId(
user, layoutRevision.getLayoutSetBranchId(),
layoutRevision.getPlid(), layoutRevision.getLayoutRevisionId());
}
else {
if (_layoutRevisionId.get() > 0) {
layoutRevision = layoutRevisionPersistence.findByPrimaryKey(
_layoutRevisionId.get());
}
else {
layoutRevision = oldLayoutRevision;
}
layoutRevision.setName(name);
layoutRevision.setTitle(title);
layoutRevision.setDescription(description);
layoutRevision.setKeywords(keywords);
layoutRevision.setRobots(robots);
layoutRevision.setTypeSettings(typeSettings);
layoutRevision.setIconImageId(iconImageId);
layoutRevision.setThemeId(themeId);
layoutRevision.setColorSchemeId(colorSchemeId);
layoutRevision.setCss(css);
layoutRevisionPersistence.update(layoutRevision);
_layoutRevisionId.set(layoutRevision.getLayoutRevisionId());
}
boolean major = ParamUtil.getBoolean(serviceContext, "major");
if (major || !isWorkflowEnabled(layoutRevision.getPlid())) {
updateMajor(layoutRevision);
}
// Workflow
if (isWorkflowEnabled(layoutRevision.getPlid())) {
WorkflowHandlerRegistryUtil.startWorkflowInstance(
layoutRevision.getCompanyId(), layoutRevision.getGroupId(),
userId, LayoutRevision.class.getName(),
layoutRevision.getLayoutRevisionId(), layoutRevision,
serviceContext);
}
else {
updateStatus(
userId, layoutRevision.getLayoutRevisionId(),
WorkflowConstants.STATUS_APPROVED, serviceContext);
}
return layoutRevision;
}
@Override
public LayoutRevision updateStatus(
long userId, long layoutRevisionId, int status,
ServiceContext serviceContext)
throws PortalException {
User user = userPersistence.findByPrimaryKey(userId);
LayoutRevision layoutRevision =
layoutRevisionPersistence.findByPrimaryKey(layoutRevisionId);
layoutRevision.setStatus(status);
layoutRevision.setStatusByUserId(user.getUserId());
layoutRevision.setStatusByUserName(user.getFullName());
layoutRevision.setStatusDate(new Date());
if (status == WorkflowConstants.STATUS_APPROVED) {
layoutRevision.setHead(true);
}
else {
layoutRevision.setHead(false);
layoutRevision.setMajor(false);
}
layoutRevisionPersistence.update(layoutRevision);
if (status == WorkflowConstants.STATUS_APPROVED) {
List<LayoutRevision> layoutRevisions =
layoutRevisionPersistence.findByL_P(
layoutRevision.getLayoutSetBranchId(),
layoutRevision.getPlid());
for (LayoutRevision curLayoutRevision : layoutRevisions) {
if (curLayoutRevision.getLayoutRevisionId() !=
layoutRevision.getLayoutRevisionId()) {
curLayoutRevision.setHead(false);
layoutRevisionPersistence.update(curLayoutRevision);
}
}
}
else {
List<LayoutRevision> layoutRevisions =
layoutRevisionPersistence.findByL_P_S(
layoutRevision.getLayoutSetBranchId(),
layoutRevision.getPlid(),
WorkflowConstants.STATUS_APPROVED);
for (LayoutRevision curLayoutRevision : layoutRevisions) {
if (curLayoutRevision.getLayoutRevisionId() !=
layoutRevision.getLayoutRevisionId()) {
curLayoutRevision.setHead(true);
layoutRevisionPersistence.update(curLayoutRevision);
break;
}
}
}
return layoutRevision;
}
protected void copyPortletPreferences(
LayoutRevision layoutRevision, long parentLayoutRevisionId) {
List<PortletPreferences> portletPreferencesList =
portletPreferencesLocalService.getPortletPreferencesByPlid(
parentLayoutRevisionId);
for (PortletPreferences portletPreferences : portletPreferencesList) {
portletPreferencesLocalService.addPortletPreferences(
layoutRevision.getCompanyId(), portletPreferences.getOwnerId(),
portletPreferences.getOwnerType(),
layoutRevision.getLayoutRevisionId(),
portletPreferences.getPortletId(), null,
portletPreferences.getPreferences());
}
}
protected long getParentLayoutRevisionId(
long layoutSetBranchId, long parentLayoutRevisionId, long plid) {
LayoutRevision parentLayoutRevision = null;
if (parentLayoutRevisionId > 0) {
parentLayoutRevision = layoutRevisionPersistence.fetchByPrimaryKey(
parentLayoutRevisionId);
if (parentLayoutRevision == null) {
List<LayoutRevision> layoutRevisions =
layoutRevisionPersistence.findByL_P(
layoutSetBranchId, plid, 0, 1);
if (!layoutRevisions.isEmpty()) {
parentLayoutRevision = layoutRevisions.get(0);
}
}
}
if (parentLayoutRevision != null) {
return parentLayoutRevision.getLayoutRevisionId();
}
return LayoutRevisionConstants.DEFAULT_PARENT_LAYOUT_REVISION_ID;
}
protected boolean isWorkflowEnabled(long plid) throws PortalException {
Layout layout = layoutLocalService.getLayout(plid);
if (layout.isTypeLinkToLayout() || layout.isTypeURL()) {
return false;
}
return true;
}
protected LayoutRevision updateMajor(LayoutRevision layoutRevision)
throws PortalException {
List<LayoutRevision> parentLayoutRevisions = new ArrayList<>();
long parentLayoutRevisionId =
layoutRevision.getParentLayoutRevisionId();
while (parentLayoutRevisionId !=
LayoutRevisionConstants.DEFAULT_PARENT_LAYOUT_REVISION_ID) {
LayoutRevision parentLayoutRevision =
layoutRevisionPersistence.findByPrimaryKey(
parentLayoutRevisionId);
if (parentLayoutRevision.isMajor()) {
break;
}
parentLayoutRevisions.add(parentLayoutRevision);
parentLayoutRevisionId =
parentLayoutRevision.getParentLayoutRevisionId();
}
layoutRevision.setParentLayoutRevisionId(parentLayoutRevisionId);
layoutRevision.setMajor(true);
layoutRevisionPersistence.update(layoutRevision);
for (LayoutRevision parentLayoutRevision : parentLayoutRevisions) {
List<LayoutRevision> childrenLayoutRevisions =
parentLayoutRevision.getChildren();
if (!childrenLayoutRevisions.isEmpty()) {
break;
}
layoutRevisionLocalService.deleteLayoutRevision(
parentLayoutRevision);
}
return layoutRevision;
}
private static final Log _log = LogFactoryUtil.getLog(
LayoutRevisionLocalServiceImpl.class);
private static final ThreadLocal<Long> _layoutRevisionId =
new AutoResetThreadLocal<>(
LayoutRevisionLocalServiceImpl.class + "._layoutRevisionId",
() -> 0L);
}