/**
* 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.knowledge.base.web.internal.portlet.action;
import com.liferay.knowledge.base.constants.KBActionKeys;
import com.liferay.knowledge.base.constants.KBFolderConstants;
import com.liferay.knowledge.base.constants.KBPortletKeys;
import com.liferay.knowledge.base.model.KBArticle;
import com.liferay.knowledge.base.model.KBFolder;
import com.liferay.knowledge.base.service.KBArticleLocalService;
import com.liferay.knowledge.base.service.KBFolderLocalService;
import com.liferay.knowledge.base.service.permission.KBArticlePermission;
import com.liferay.knowledge.base.service.util.AdminUtil;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.model.Group;
import com.liferay.portal.kernel.model.Layout;
import com.liferay.portal.kernel.model.LayoutConstants;
import com.liferay.portal.kernel.model.LayoutTypePortlet;
import com.liferay.portal.kernel.model.Portlet;
import com.liferay.portal.kernel.model.PortletConstants;
import com.liferay.portal.kernel.portlet.LiferayWindowState;
import com.liferay.portal.kernel.portlet.PortletPreferencesFactoryUtil;
import com.liferay.portal.kernel.portlet.PortletURLFactoryUtil;
import com.liferay.portal.kernel.security.auth.AuthTokenUtil;
import com.liferay.portal.kernel.security.permission.PermissionChecker;
import com.liferay.portal.kernel.security.permission.PermissionThreadLocal;
import com.liferay.portal.kernel.service.GroupLocalService;
import com.liferay.portal.kernel.service.LayoutLocalService;
import com.liferay.portal.kernel.struts.BaseStrutsAction;
import com.liferay.portal.kernel.struts.StrutsAction;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.ParamUtil;
import com.liferay.portal.kernel.util.Portal;
import com.liferay.portal.kernel.util.PropsKeys;
import com.liferay.portal.kernel.util.PropsUtil;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.kernel.workflow.WorkflowConstants;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javax.portlet.PortletMode;
import javax.portlet.PortletPreferences;
import javax.portlet.PortletRequest;
import javax.portlet.PortletURL;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* @author Peter Shin
*/
@Component(
immediate = true, property = "path=/knowledge_base/find_kb_article",
service = StrutsAction.class
)
public class FindKBArticleAction extends BaseStrutsAction {
@Override
public String execute(
StrutsAction originalStrutsAction, HttpServletRequest request,
HttpServletResponse response)
throws Exception {
ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
WebKeys.THEME_DISPLAY);
long plid = ParamUtil.getLong(request, "plid");
long resourcePrimKey = ParamUtil.getLong(request, "resourcePrimKey");
int status = ParamUtil.getInteger(
request, "status", WorkflowConstants.STATUS_APPROVED);
boolean maximized = ParamUtil.getBoolean(request, "maximized");
KBArticle kbArticle = getKBArticle(resourcePrimKey, status);
if (!isValidPlid(plid)) {
plid = themeDisplay.getPlid();
}
PortletURL portletURL = null;
if (kbArticle == null) {
portletURL = getDynamicPortletURL(plid, status, request);
}
if (status != WorkflowConstants.STATUS_APPROVED) {
portletURL = getDynamicPortletURL(plid, status, request);
}
if (portletURL == null) {
portletURL = getKBArticleURL(plid, false, kbArticle, request);
}
if (portletURL == null) {
portletURL = getKBArticleURL(plid, true, kbArticle, request);
}
if (portletURL == null) {
portletURL = getDynamicPortletURL(plid, status, request);
}
if (maximized) {
portletURL.setWindowState(LiferayWindowState.MAXIMIZED);
portletURL.setPortletMode(PortletMode.VIEW);
}
response.sendRedirect(portletURL.toString());
return null;
}
protected List<Layout> getCandidateLayouts(
long plid, boolean privateLayout, KBArticle kbArticle)
throws Exception {
List<Layout> candidateLayouts = new ArrayList<>();
Group group = _groupLocalService.getGroup(kbArticle.getGroupId());
if (group.isLayout()) {
Layout layout = _layoutLocalService.getLayout(group.getClassPK());
candidateLayouts.add(layout);
group = layout.getGroup();
}
List<Layout> layouts = _layoutLocalService.getLayouts(
group.getGroupId(), privateLayout, LayoutConstants.TYPE_PORTLET);
candidateLayouts.addAll(layouts);
Layout layout = _layoutLocalService.getLayout(plid);
if ((layout.getGroupId() == kbArticle.getGroupId()) &&
layout.isTypePortlet()) {
candidateLayouts.remove(layout);
candidateLayouts.add(0, layout);
}
return candidateLayouts;
}
protected PortletURL getDynamicPortletURL(
long plid, int status, HttpServletRequest request)
throws Exception {
String portletId = getPortletId(plid);
PortletURL portletURL = getKBArticleURL(plid, portletId, null, request);
if (status != WorkflowConstants.STATUS_APPROVED) {
portletURL.setParameter("status", String.valueOf(status));
}
if (_PORTLET_ADD_DEFAULT_RESOURCE_CHECK_ENABLED) {
String token = AuthTokenUtil.getToken(request, plid, portletId);
portletURL.setParameter("p_p_auth", token);
}
portletURL.setPortletMode(PortletMode.VIEW);
if (Objects.equals(
portletId,
KBPortletKeys.KNOWLEDGE_BASE_ARTICLE_DEFAULT_INSTANCE)) {
portletURL.setWindowState(LiferayWindowState.MAXIMIZED);
}
return portletURL;
}
protected KBArticle getKBArticle(long resourcePrimKey, int status)
throws Exception {
KBArticle kbArticle = _kbArticleLocalService.fetchLatestKBArticle(
resourcePrimKey, status);
if (kbArticle == null) {
return null;
}
PermissionChecker permissionChecker =
PermissionThreadLocal.getPermissionChecker();
if (!KBArticlePermission.contains(
permissionChecker, kbArticle, KBActionKeys.VIEW)) {
return null;
}
return kbArticle;
}
protected PortletURL getKBArticleURL(
long plid, boolean privateLayout, KBArticle kbArticle,
HttpServletRequest request)
throws Exception {
PortletURL firstMatchPortletURL = null;
List<Layout> layouts = getCandidateLayouts(
plid, privateLayout, kbArticle);
for (Layout layout : layouts) {
LayoutTypePortlet layoutTypePortlet =
(LayoutTypePortlet)layout.getLayoutType();
List<Portlet> portlets = layoutTypePortlet.getAllPortlets();
for (Portlet portlet : portlets) {
String rootPortletId = PortletConstants.getRootPortletId(
portlet.getPortletId());
if (rootPortletId.equals(
KBPortletKeys.KNOWLEDGE_BASE_DISPLAY)) {
PortletPreferences portletPreferences =
PortletPreferencesFactoryUtil.getPortletSetup(
layout, portlet.getPortletId(), StringPool.BLANK);
long kbFolderClassNameId = _portal.getClassNameId(
KBFolderConstants.getClassName());
long resourceClassNameId = GetterUtil.getLong(
portletPreferences.getValue(
"resourceClassNameId", null),
kbFolderClassNameId);
long resourcePrimKey = GetterUtil.getLong(
portletPreferences.getValue("resourcePrimKey", null),
KBFolderConstants.DEFAULT_PARENT_FOLDER_ID);
if (resourceClassNameId == kbFolderClassNameId) {
if (isParentFolder(
resourcePrimKey, kbArticle.getKbFolderId())) {
return getKBArticleURL(
layout.getPlid(), portlet.getPortletId(),
kbArticle, request);
}
}
else if (resourcePrimKey ==
kbArticle.getResourcePrimKey()) {
return getKBArticleURL(
layout.getPlid(), portlet.getPortletId(), kbArticle,
request);
}
if (firstMatchPortletURL == null) {
firstMatchPortletURL = getKBArticleURL(
layout.getPlid(), portlet.getPortletId(), kbArticle,
request);
}
}
if (rootPortletId.equals(
KBPortletKeys.KNOWLEDGE_BASE_SECTION)) {
PortletPreferences portletPreferences =
PortletPreferencesFactoryUtil.getPortletSetup(
layout, portlet.getPortletId(), StringPool.BLANK);
String[] kbArticlesSections = portletPreferences.getValues(
"kbArticlesSections", new String[0]);
KBArticle rootKBArticle =
_kbArticleLocalService.fetchLatestKBArticle(
kbArticle.getRootResourcePrimKey(),
WorkflowConstants.STATUS_APPROVED);
if (rootKBArticle == null) {
continue;
}
String[] sections = AdminUtil.unescapeSections(
rootKBArticle.getSections());
for (String section : sections) {
if (!ArrayUtil.contains(kbArticlesSections, section)) {
continue;
}
return getKBArticleURL(
layout.getPlid(), portlet.getPortletId(), kbArticle,
request);
}
}
if (rootPortletId.equals(
KBPortletKeys.KNOWLEDGE_BASE_ARTICLE)) {
PortletPreferences portletPreferences =
PortletPreferencesFactoryUtil.getPortletSetup(
layout, portlet.getPortletId(), StringPool.BLANK);
long resourcePrimKey = GetterUtil.getLong(
portletPreferences.getValue("resourcePrimKey", null));
KBArticle selKBArticle =
_kbArticleLocalService.fetchLatestKBArticle(
resourcePrimKey, WorkflowConstants.STATUS_APPROVED);
if (selKBArticle == null) {
continue;
}
long rootResourcePrimKey =
kbArticle.getRootResourcePrimKey();
long selRootResourcePrimKey =
selKBArticle.getRootResourcePrimKey();
if (rootResourcePrimKey == selRootResourcePrimKey) {
return getKBArticleURL(
layout.getPlid(), portlet.getPortletId(), kbArticle,
request);
}
if (firstMatchPortletURL == null) {
firstMatchPortletURL = getKBArticleURL(
layout.getPlid(), portlet.getPortletId(), kbArticle,
request);
}
}
}
}
return firstMatchPortletURL;
}
protected PortletURL getKBArticleURL(
long plid, String portletId, KBArticle kbArticle,
HttpServletRequest request)
throws Exception {
long resourcePrimKey = ParamUtil.getLong(request, "resourcePrimKey");
String mvcPath = null;
String rootPortletId = PortletConstants.getRootPortletId(portletId);
if (rootPortletId.equals(KBPortletKeys.KNOWLEDGE_BASE_ARTICLE)) {
mvcPath = "/article/view_article.jsp";
}
else if (rootPortletId.equals(KBPortletKeys.KNOWLEDGE_BASE_SECTION)) {
mvcPath = "/section/view_article.jsp";
}
PortletURL portletURL = PortletURLFactoryUtil.create(
request, portletId, plid, PortletRequest.RENDER_PHASE);
if (mvcPath != null) {
portletURL.setParameter("mvcPath", mvcPath);
}
if ((kbArticle == null) || Validator.isNull(kbArticle.getUrlTitle())) {
portletURL.setParameter(
"resourcePrimKey", String.valueOf(resourcePrimKey));
}
else {
portletURL.setParameter("urlTitle", kbArticle.getUrlTitle());
if (kbArticle.getKbFolderId() !=
KBFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
KBFolder kbFolder = _kbFolderLocalService.getKBFolder(
kbArticle.getKbFolderId());
portletURL.setParameter(
"kbFolderUrlTitle", String.valueOf(kbFolder.getUrlTitle()));
}
}
portletURL.setPortletMode(PortletMode.VIEW);
portletURL.setWindowState(LiferayWindowState.NORMAL);
if (rootPortletId.equals(KBPortletKeys.KNOWLEDGE_BASE_SECTION)) {
portletURL.setWindowState(LiferayWindowState.MAXIMIZED);
}
return portletURL;
}
protected String getPortletId(long plid) throws Exception {
Layout layout = _layoutLocalService.getLayout(plid);
long selPlid = _portal.getPlidFromPortletId(
layout.getGroupId(), KBPortletKeys.KNOWLEDGE_BASE_DISPLAY);
if (selPlid != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
return KBPortletKeys.KNOWLEDGE_BASE_DISPLAY;
}
return KBPortletKeys.KNOWLEDGE_BASE_ARTICLE_DEFAULT_INSTANCE;
}
protected boolean isParentFolder(long resourcePrimKey, long kbFolderId)
throws PortalException {
if (resourcePrimKey == kbFolderId) {
return true;
}
while (kbFolderId != KBFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
if (resourcePrimKey == kbFolderId) {
return true;
}
KBFolder kbFolder = _kbFolderLocalService.getKBFolder(kbFolderId);
kbFolderId = kbFolder.getParentKBFolderId();
}
return false;
}
protected boolean isValidPlid(long plid) throws Exception {
Layout layout = _layoutLocalService.fetchLayout(plid);
if (layout == null) {
return false;
}
return true;
}
@Reference(unbind = "-")
protected void setGroupLocalService(GroupLocalService groupLocalService) {
_groupLocalService = groupLocalService;
}
@Reference(unbind = "-")
protected void setKBArticleLocalService(
KBArticleLocalService kbArticleLocalService) {
_kbArticleLocalService = kbArticleLocalService;
}
@Reference(unbind = "-")
protected void setKBFolderLocalService(
KBFolderLocalService kbFolderLocalService) {
_kbFolderLocalService = kbFolderLocalService;
}
@Reference(unbind = "-")
protected void setLayoutLocalService(
LayoutLocalService layoutLocalService) {
_layoutLocalService = layoutLocalService;
}
private static final boolean _PORTLET_ADD_DEFAULT_RESOURCE_CHECK_ENABLED =
GetterUtil.getBoolean(
PropsUtil.get(
PropsKeys.PORTLET_ADD_DEFAULT_RESOURCE_CHECK_ENABLED));
private GroupLocalService _groupLocalService;
private KBArticleLocalService _kbArticleLocalService;
private KBFolderLocalService _kbFolderLocalService;
private LayoutLocalService _layoutLocalService;
@Reference
private Portal _portal;
}