/** * 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.portlet.messageboards.service.impl; import com.liferay.asset.kernel.model.AssetEntry; import com.liferay.asset.kernel.model.AssetLinkConstants; import com.liferay.document.library.kernel.model.DLFolderConstants; import com.liferay.message.boards.kernel.constants.MBConstants; import com.liferay.message.boards.kernel.exception.DiscussionMaxCommentsException; import com.liferay.message.boards.kernel.exception.MessageBodyException; import com.liferay.message.boards.kernel.exception.MessageSubjectException; import com.liferay.message.boards.kernel.exception.NoSuchThreadException; import com.liferay.message.boards.kernel.exception.RequiredMessageException; import com.liferay.message.boards.kernel.model.MBCategory; import com.liferay.message.boards.kernel.model.MBCategoryConstants; import com.liferay.message.boards.kernel.model.MBDiscussion; import com.liferay.message.boards.kernel.model.MBMessage; import com.liferay.message.boards.kernel.model.MBMessageConstants; import com.liferay.message.boards.kernel.model.MBMessageDisplay; import com.liferay.message.boards.kernel.model.MBThread; import com.liferay.message.boards.kernel.model.MBThreadConstants; import com.liferay.message.boards.kernel.util.comparator.MessageCreateDateComparator; import com.liferay.message.boards.kernel.util.comparator.MessageThreadComparator; import com.liferay.portal.kernel.dao.orm.QueryDefinition; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.exception.SystemException; import com.liferay.portal.kernel.json.JSONFactoryUtil; import com.liferay.portal.kernel.json.JSONObject; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.model.Group; import com.liferay.portal.kernel.model.ModelHintsUtil; import com.liferay.portal.kernel.model.ResourceConstants; import com.liferay.portal.kernel.model.SystemEventConstants; import com.liferay.portal.kernel.model.User; import com.liferay.portal.kernel.portlet.PortletProvider; import com.liferay.portal.kernel.portlet.PortletProviderUtil; import com.liferay.portal.kernel.portletfilerepository.PortletFileRepositoryUtil; import com.liferay.portal.kernel.repository.model.FileEntry; import com.liferay.portal.kernel.repository.model.Folder; import com.liferay.portal.kernel.sanitizer.Sanitizer; import com.liferay.portal.kernel.sanitizer.SanitizerUtil; import com.liferay.portal.kernel.search.Indexable; import com.liferay.portal.kernel.search.IndexableType; import com.liferay.portal.kernel.search.Indexer; import com.liferay.portal.kernel.search.IndexerRegistryUtil; import com.liferay.portal.kernel.security.auth.PrincipalException; import com.liferay.portal.kernel.security.permission.ActionKeys; import com.liferay.portal.kernel.service.ServiceContext; import com.liferay.portal.kernel.service.permission.ModelPermissions; import com.liferay.portal.kernel.settings.LocalizedValuesMap; import com.liferay.portal.kernel.social.SocialActivityManagerUtil; import com.liferay.portal.kernel.systemevent.SystemEvent; import com.liferay.portal.kernel.util.Constants; import com.liferay.portal.kernel.util.ContentTypes; import com.liferay.portal.kernel.util.GetterUtil; import com.liferay.portal.kernel.util.HtmlUtil; import com.liferay.portal.kernel.util.ListUtil; import com.liferay.portal.kernel.util.ObjectValuePair; import com.liferay.portal.kernel.util.OrderByComparator; import com.liferay.portal.kernel.util.ParamUtil; import com.liferay.portal.kernel.util.Portal; import com.liferay.portal.kernel.util.PortalUtil; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.kernel.workflow.WorkflowConstants; import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil; import com.liferay.portal.kernel.workflow.WorkflowThreadLocal; import com.liferay.portal.linkback.LinkbackProducerUtil; import com.liferay.portal.util.LayoutURLUtil; import com.liferay.portal.util.PropsValues; import com.liferay.portlet.messageboards.MBGroupServiceSettings; import com.liferay.portlet.messageboards.model.impl.MBCategoryImpl; import com.liferay.portlet.messageboards.model.impl.MBMessageDisplayImpl; import com.liferay.portlet.messageboards.service.base.MBMessageLocalServiceBaseImpl; import com.liferay.portlet.messageboards.social.MBActivityKeys; import com.liferay.portlet.messageboards.util.MBSubscriptionSender; import com.liferay.portlet.messageboards.util.MBUtil; import com.liferay.social.kernel.model.SocialActivityConstants; import com.liferay.trash.kernel.util.TrashUtil; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.portlet.PortletRequest; import javax.portlet.PortletURL; import javax.servlet.http.HttpServletRequest; import net.htmlparser.jericho.Source; import net.htmlparser.jericho.StartTag; /** * @author Brian Wing Shun Chan * @author Raymond Augé * @author Mika Koivisto * @author Jorge Ferrer * @author Juan Fernández * @author Shuyang Zhou */ public class MBMessageLocalServiceImpl extends MBMessageLocalServiceBaseImpl { @Override public MBMessage addDiscussionMessage( long userId, String userName, long groupId, String className, long classPK, int workflowAction) throws PortalException { long threadId = 0; long parentMessageId = MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID; String subject = String.valueOf(classPK); String body = subject; ServiceContext serviceContext = new ServiceContext(); serviceContext.setWorkflowAction(workflowAction); boolean workflowEnabled = WorkflowThreadLocal.isEnabled(); WorkflowThreadLocal.setEnabled(false); try { return addDiscussionMessage( userId, userName, groupId, className, classPK, threadId, parentMessageId, subject, body, serviceContext); } finally { WorkflowThreadLocal.setEnabled(workflowEnabled); } } @Override public MBMessage addDiscussionMessage( long userId, String userName, long groupId, String className, long classPK, long threadId, long parentMessageId, String subject, String body, ServiceContext serviceContext) throws PortalException { // Message validateDiscussionMaxComments(className, classPK); long categoryId = MBCategoryConstants.DISCUSSION_CATEGORY_ID; subject = getDiscussionMessageSubject(subject, body); List<ObjectValuePair<String, InputStream>> inputStreamOVPs = Collections.emptyList(); boolean anonymous = false; double priority = 0.0; boolean allowPingbacks = false; serviceContext.setAddGroupPermissions(true); serviceContext.setAddGuestPermissions(true); serviceContext.setAttribute("className", className); serviceContext.setAttribute("classPK", String.valueOf(classPK)); Date now = new Date(); if (serviceContext.getCreateDate() == null) { serviceContext.setCreateDate(now); } if (serviceContext.getModifiedDate() == null) { serviceContext.setModifiedDate(now); } MBMessage message = addMessage( userId, userName, groupId, categoryId, threadId, parentMessageId, subject, body, PropsValues.DISCUSSION_COMMENTS_FORMAT, inputStreamOVPs, anonymous, priority, allowPingbacks, serviceContext); // Discussion if (parentMessageId == MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID) { long classNameId = classNameLocalService.getClassNameId(className); MBDiscussion discussion = mbDiscussionPersistence.fetchByC_C( classNameId, classPK); if (discussion == null) { mbDiscussionLocalService.addDiscussion( userId, groupId, classNameId, classPK, message.getThreadId(), serviceContext); } } return message; } @Override public MBMessage addMessage( long userId, String userName, long groupId, long categoryId, long threadId, long parentMessageId, String subject, String body, String format, List<ObjectValuePair<String, InputStream>> inputStreamOVPs, boolean anonymous, double priority, boolean allowPingbacks, ServiceContext serviceContext) throws PortalException { // Message User user = userPersistence.findByPrimaryKey(userId); userName = user.isDefaultUser() ? userName : user.getFullName(); subject = ModelHintsUtil.trimString( MBMessage.class.getName(), "subject", subject); if (!MBUtil.isValidMessageFormat(format)) { format = "html"; } MBGroupServiceSettings mbGroupServiceSettings = MBGroupServiceSettings.getInstance(groupId); if (mbGroupServiceSettings != null) { if (!mbGroupServiceSettings.isAllowAnonymousPosting()) { if (anonymous || user.isDefaultUser()) { throw new PrincipalException.MustHavePermission( userId, ActionKeys.ADD_MESSAGE); } } } if (user.isDefaultUser()) { anonymous = true; } Date now = new Date(); long messageId = counterLocalService.increment(); subject = getSubject(subject, body); body = getBody(subject, body); Map<String, Object> options = new HashMap<>(); boolean discussion = false; if (categoryId == MBCategoryConstants.DISCUSSION_CATEGORY_ID) { discussion = true; } options.put("discussion", discussion); body = SanitizerUtil.sanitize( user.getCompanyId(), groupId, userId, MBMessage.class.getName(), messageId, "text/" + format, Sanitizer.MODE_ALL, body, options); validate(subject, body); MBMessage message = mbMessagePersistence.create(messageId); message.setUuid(serviceContext.getUuid()); message.setGroupId(groupId); message.setCompanyId(user.getCompanyId()); message.setUserId(user.getUserId()); message.setUserName(userName); message.setCreateDate(serviceContext.getCreateDate(now)); message.setModifiedDate(serviceContext.getModifiedDate(now)); if (threadId > 0) { message.setThreadId(threadId); } if (priority != MBThreadConstants.PRIORITY_NOT_GIVEN) { message.setPriority(priority); } message.setAllowPingbacks(allowPingbacks); message.setStatus(WorkflowConstants.STATUS_DRAFT); message.setStatusByUserId(user.getUserId()); message.setStatusByUserName(userName); message.setStatusDate(serviceContext.getModifiedDate(now)); // Thread if (parentMessageId != MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID) { MBMessage parentMessage = mbMessagePersistence.fetchByPrimaryKey( parentMessageId); if (parentMessage == null) { parentMessageId = MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID; } } MBThread thread = null; if (threadId > 0) { thread = mbThreadPersistence.fetchByPrimaryKey(threadId); } if (thread == null) { if (parentMessageId == MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID) { thread = mbThreadLocalService.addThread( categoryId, message, serviceContext); } else { throw new NoSuchThreadException("{threadId=" + threadId + "}"); } } if ((priority != MBThreadConstants.PRIORITY_NOT_GIVEN) && (thread.getPriority() != priority)) { thread.setPriority(priority); mbThreadPersistence.update(thread); updatePriorities(thread.getThreadId(), priority); } // Message message.setCategoryId(categoryId); message.setThreadId(thread.getThreadId()); message.setRootMessageId(thread.getRootMessageId()); message.setParentMessageId(parentMessageId); message.setSubject(subject); message.setBody(body); message.setFormat(format); message.setAnonymous(anonymous); if (message.isDiscussion()) { long classNameId = classNameLocalService.getClassNameId( (String)serviceContext.getAttribute("className")); long classPK = ParamUtil.getLong(serviceContext, "classPK"); message.setClassNameId(classNameId); message.setClassPK(classPK); } message.setExpandoBridgeAttributes(serviceContext); mbMessagePersistence.update(message); // Resources if ((parentMessageId != MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID) && GetterUtil.getBoolean( serviceContext.getAttribute("propagatePermissions"))) { MBUtil.propagatePermissions( message.getCompanyId(), groupId, parentMessageId, serviceContext); } if (!message.isDiscussion()) { if (user.isDefaultUser()) { addMessageResources(message, true, true); } else if (serviceContext.isAddGroupPermissions() || serviceContext.isAddGuestPermissions()) { addMessageResources( message, serviceContext.isAddGroupPermissions(), serviceContext.isAddGuestPermissions()); } else { addMessageResources( message, serviceContext.getModelPermissions()); } } // Attachments if (ListUtil.isNotEmpty(inputStreamOVPs)) { Folder folder = message.addAttachmentsFolder(); PortletFileRepositoryUtil.addPortletFileEntries( message.getGroupId(), userId, MBMessage.class.getName(), message.getMessageId(), MBConstants.SERVICE_NAME, folder.getFolderId(), inputStreamOVPs); } // Asset updateAsset( userId, message, serviceContext.getAssetCategoryIds(), serviceContext.getAssetTagNames(), serviceContext.getAssetLinkEntryIds(), serviceContext.isAssetEntryVisible()); // Workflow startWorkflowInstance(userId, message, serviceContext); return message; } @Override public MBMessage addMessage( long userId, String userName, long groupId, long categoryId, String subject, String body, ServiceContext serviceContext) throws PortalException { List<ObjectValuePair<String, InputStream>> inputStreamOVPs = Collections.emptyList(); return addMessage( userId, userName, groupId, categoryId, 0, 0, subject, body, MBMessageConstants.DEFAULT_FORMAT, inputStreamOVPs, false, 0.0, false, serviceContext); } @Override public MBMessage addMessage( long userId, String userName, long groupId, long categoryId, String subject, String body, String format, List<ObjectValuePair<String, InputStream>> inputStreamOVPs, boolean anonymous, double priority, boolean allowPingbacks, ServiceContext serviceContext) throws PortalException { long threadId = 0; long parentMessageId = MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID; return addMessage( userId, userName, groupId, categoryId, threadId, parentMessageId, subject, body, format, inputStreamOVPs, anonymous, priority, allowPingbacks, serviceContext); } @Override public MBMessage addMessage( long userId, String userName, long groupId, long categoryId, String subject, String body, String format, String fileName, File file, boolean anonymous, double priority, boolean allowPingbacks, ServiceContext serviceContext) throws FileNotFoundException, PortalException { List<ObjectValuePair<String, InputStream>> inputStreamOVPs = new ArrayList<>(1); InputStream inputStream = new FileInputStream(file); ObjectValuePair<String, InputStream> inputStreamOVP = new ObjectValuePair<>(fileName, inputStream); inputStreamOVPs.add(inputStreamOVP); return addMessage( userId, userName, groupId, categoryId, 0, 0, subject, body, format, inputStreamOVPs, anonymous, priority, allowPingbacks, serviceContext); } /** * @deprecated As of 7.0.0, replaced by {@link #addMessage(long, String, * long, long, String, String, ServiceContext)} */ @Deprecated @Override public MBMessage addMessage( long userId, String userName, long categoryId, String subject, String body, ServiceContext serviceContext) throws PortalException { long groupId = serviceContext.getScopeGroupId(); if (categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) { MBCategory category = mbCategoryPersistence.findByPrimaryKey( categoryId); groupId = category.getGroupId(); } return addMessage( userId, userName, groupId, categoryId, subject, body, serviceContext); } @Override public void addMessageAttachment( long userId, long messageId, String fileName, File file, String mimeType) throws PortalException { MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId); Folder folder = message.addAttachmentsFolder(); PortletFileRepositoryUtil.addPortletFileEntry( message.getGroupId(), userId, MBMessage.class.getName(), message.getMessageId(), MBConstants.SERVICE_NAME, folder.getFolderId(), file, fileName, mimeType, true); } @Override public void addMessageResources( long messageId, boolean addGroupPermissions, boolean addGuestPermissions) throws PortalException { MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId); addMessageResources(message, addGroupPermissions, addGuestPermissions); } @Override public void addMessageResources( long messageId, ModelPermissions modelPermissions) throws PortalException { MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId); addMessageResources(message, modelPermissions); } @Override public void addMessageResources( MBMessage message, boolean addGroupPermissions, boolean addGuestPermissions) throws PortalException { resourceLocalService.addResources( message.getCompanyId(), message.getGroupId(), message.getUserId(), MBMessage.class.getName(), message.getMessageId(), false, addGroupPermissions, addGuestPermissions); } @Override public void addMessageResources( MBMessage message, ModelPermissions modelPermissions) throws PortalException { resourceLocalService.addModelResources( message.getCompanyId(), message.getGroupId(), message.getUserId(), MBMessage.class.getName(), message.getMessageId(), modelPermissions); } @Indexable(type = IndexableType.DELETE) @Override public MBMessage deleteDiscussionMessage(long messageId) throws PortalException { MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId); SocialActivityManagerUtil.deleteActivities(message); return mbMessageLocalService.deleteMessage(messageId); } @Override public void deleteDiscussionMessages(String className, long classPK) throws PortalException { long classNameId = classNameLocalService.getClassNameId(className); MBDiscussion discussion = mbDiscussionPersistence.fetchByC_C( classNameId, classPK); if (discussion == null) { if (_log.isInfoEnabled()) { _log.info( "Unable to delete discussion message for class name " + className + " and class PK " + classPK + " because it does not exist"); } return; } List<MBMessage> messages = mbMessagePersistence.findByT_P( discussion.getThreadId(), MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID, 0, 1); if (!messages.isEmpty()) { MBMessage message = messages.get(0); SocialActivityManagerUtil.deleteActivities(message); mbThreadLocalService.deleteThread(message.getThreadId()); } mbDiscussionPersistence.remove(discussion); } @Indexable(type = IndexableType.DELETE) @Override public MBMessage deleteMessage(long messageId) throws PortalException { MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId); return mbMessageLocalService.deleteMessage(message); } @Indexable(type = IndexableType.DELETE) @Override @SystemEvent(type = SystemEventConstants.TYPE_DELETE) public MBMessage deleteMessage(MBMessage message) throws PortalException { // Attachments long folderId = message.getAttachmentsFolderId(); if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) { PortletFileRepositoryUtil.deletePortletFolder(folderId); } // Thread int count = mbMessagePersistence.countByThreadId(message.getThreadId()); if (count == 1) { // Attachments long threadAttachmentsFolderId = message.getThreadAttachmentsFolderId(); if (threadAttachmentsFolderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) { PortletFileRepositoryUtil.deletePortletFolder( threadAttachmentsFolderId); } // Thread MBThread thread = mbThreadPersistence.findByPrimaryKey( message.getThreadId()); mbThreadPersistence.remove(thread); // Category if ((message.getCategoryId() != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) && (message.getCategoryId() != MBCategoryConstants.DISCUSSION_CATEGORY_ID)) { MBUtil.updateCategoryStatistics(message.getCategoryId()); } // Indexer Indexer<MBThread> indexer = IndexerRegistryUtil.nullSafeGetIndexer( MBThread.class); indexer.delete(thread); } else { MBThread thread = mbThreadPersistence.findByPrimaryKey( message.getThreadId()); // Message is a root message if (thread.getRootMessageId() == message.getMessageId()) { List<MBMessage> childrenMessages = mbMessagePersistence.findByT_P( message.getThreadId(), message.getMessageId()); if (childrenMessages.size() > 1) { throw new RequiredMessageException( String.valueOf(message.getMessageId())); } else if (childrenMessages.size() == 1) { MBMessage childMessage = childrenMessages.get(0); childMessage.setRootMessageId(childMessage.getMessageId()); childMessage.setParentMessageId( MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID); mbMessagePersistence.update(childMessage); List<MBMessage> repliesMessages = mbMessagePersistence.findByThreadReplies( message.getThreadId()); for (MBMessage repliesMessage : repliesMessages) { repliesMessage.setRootMessageId( childMessage.getMessageId()); mbMessagePersistence.update(repliesMessage); } thread.setRootMessageId(childMessage.getMessageId()); thread.setRootMessageUserId(childMessage.getUserId()); mbThreadPersistence.update(thread); } } else { // Message is a child message List<MBMessage> childrenMessages = mbMessagePersistence.findByT_P( message.getThreadId(), message.getMessageId()); // Message has children messages if (!childrenMessages.isEmpty()) { for (MBMessage childMessage : childrenMessages) { childMessage.setParentMessageId( message.getParentMessageId()); mbMessagePersistence.update(childMessage); } } else if (message.getStatus() == WorkflowConstants.STATUS_APPROVED) { MessageCreateDateComparator comparator = new MessageCreateDateComparator(true); MBMessage[] prevAndNextMessages = mbMessagePersistence.findByT_S_PrevAndNext( message.getMessageId(), thread.getThreadId(), WorkflowConstants.STATUS_APPROVED, comparator); if (prevAndNextMessages[2] == null) { thread.setLastPostByUserId( prevAndNextMessages[0].getUserId()); thread.setLastPostDate( prevAndNextMessages[0].getModifiedDate()); mbThreadPersistence.update(thread); } } } // Thread if (message.isApproved()) { MBUtil.updateThreadMessageCount(thread.getThreadId()); } // Category if ((message.getCategoryId() != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) && (message.getCategoryId() != MBCategoryConstants.DISCUSSION_CATEGORY_ID) && !message.isDraft()) { MBUtil.updateCategoryMessageCount(message.getCategoryId()); } // Indexer Indexer<MBThread> indexer = IndexerRegistryUtil.nullSafeGetIndexer( MBThread.class); indexer.reindex(thread); } // Asset assetEntryLocalService.deleteEntry( message.getWorkflowClassName(), message.getMessageId()); // Expando expandoRowLocalService.deleteRows(message.getMessageId()); // Ratings ratingsStatsLocalService.deleteStats( message.getWorkflowClassName(), message.getMessageId()); // Resources if (!message.isDiscussion()) { resourceLocalService.deleteResource( message.getCompanyId(), message.getWorkflowClassName(), ResourceConstants.SCOPE_INDIVIDUAL, message.getMessageId()); } // Message mbMessagePersistence.remove(message); // Statistics if (!message.isDiscussion()) { mbStatsUserLocalService.updateStatsUser( message.getGroupId(), message.getUserId()); } // Workflow workflowInstanceLinkLocalService.deleteWorkflowInstanceLinks( message.getCompanyId(), message.getGroupId(), message.getWorkflowClassName(), message.getMessageId()); return message; } @Override public void deleteMessageAttachment(long messageId, String fileName) throws PortalException { MBMessage message = getMessage(messageId); long folderId = message.getAttachmentsFolderId(); if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) { return; } PortletFileRepositoryUtil.deletePortletFileEntry( message.getGroupId(), folderId, fileName); } @Override public void deleteMessageAttachments(long messageId) throws PortalException { MBMessage message = getMessage(messageId); long folderId = message.getAttachmentsFolderId(); if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) { return; } PortletFileRepositoryUtil.deletePortletFileEntries( message.getGroupId(), folderId); } @Override public void emptyMessageAttachments(long messageId) throws PortalException { MBMessage message = getMessage(messageId); long folderId = message.getAttachmentsFolderId(); if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) { return; } PortletFileRepositoryUtil.deletePortletFileEntries( message.getGroupId(), folderId, WorkflowConstants.STATUS_IN_TRASH); } @Override public List<MBMessage> getCategoryMessages( long groupId, long categoryId, int status, int start, int end) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.findByG_C( groupId, categoryId, start, end); } else { return mbMessagePersistence.findByG_C_S( groupId, categoryId, status, start, end); } } @Override public List<MBMessage> getCategoryMessages( long groupId, long categoryId, int status, int start, int end, OrderByComparator<MBMessage> obc) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.findByG_C( groupId, categoryId, start, end, obc); } else { return mbMessagePersistence.findByG_C_S( groupId, categoryId, status, start, end, obc); } } @Override public int getCategoryMessagesCount( long groupId, long categoryId, int status) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.countByG_C(groupId, categoryId); } else { return mbMessagePersistence.countByG_C_S( groupId, categoryId, status); } } @Override public List<MBMessage> getCompanyMessages( long companyId, int status, int start, int end) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.findByCompanyId(companyId, start, end); } else { return mbMessagePersistence.findByC_S( companyId, status, start, end); } } @Override public List<MBMessage> getCompanyMessages( long companyId, int status, int start, int end, OrderByComparator<MBMessage> obc) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.findByCompanyId( companyId, start, end, obc); } else { return mbMessagePersistence.findByC_S( companyId, status, start, end, obc); } } @Override public int getCompanyMessagesCount(long companyId, int status) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.countByCompanyId(companyId); } else { return mbMessagePersistence.countByC_S(companyId, status); } } @Override public MBMessageDisplay getDiscussionMessageDisplay( long userId, long groupId, String className, long classPK, int status) throws PortalException { return getDiscussionMessageDisplay( userId, groupId, className, classPK, status, new MessageThreadComparator()); } @Override public MBMessageDisplay getDiscussionMessageDisplay( long userId, long groupId, String className, long classPK, int status, Comparator<MBMessage> comparator) throws PortalException { long classNameId = classNameLocalService.getClassNameId(className); MBMessage message = null; MBDiscussion discussion = mbDiscussionPersistence.fetchByC_C( classNameId, classPK); if (discussion != null) { message = mbMessagePersistence.findByT_P_First( discussion.getThreadId(), MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID, null); } else { boolean workflowEnabled = WorkflowThreadLocal.isEnabled(); WorkflowThreadLocal.setEnabled(false); try { String subject = String.valueOf(classPK); //String body = subject; message = addDiscussionMessage( userId, null, groupId, className, classPK, 0, MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID, subject, subject, new ServiceContext()); } catch (SystemException se) { if (_log.isWarnEnabled()) { _log.warn( "Add failed, fetch {threadId=0, parentMessageId=" + MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID + "}"); } message = mbMessagePersistence.fetchByT_P_First( 0, MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID, null); if (message == null) { throw se; } } finally { WorkflowThreadLocal.setEnabled(workflowEnabled); } } return getMessageDisplay(userId, message, status, comparator); } /** * @deprecated As of 7.0.0, replaced by {@link * #getDiscussionMessageDisplay(long, long, String, long, int)} */ @Deprecated @Override public MBMessageDisplay getDiscussionMessageDisplay( long userId, long groupId, String className, long classPK, int status, String threadView) throws PortalException { return getDiscussionMessageDisplay( userId, groupId, className, classPK, status); } @Override public int getDiscussionMessagesCount( long classNameId, long classPK, int status) { MBDiscussion discussion = mbDiscussionPersistence.fetchByC_C( classNameId, classPK); if (discussion == null) { return 0; } int count = 0; if (status == WorkflowConstants.STATUS_ANY) { count = mbMessagePersistence.countByThreadId( discussion.getThreadId()); } else { count = mbMessagePersistence.countByT_S( discussion.getThreadId(), status); } if (count >= 1) { return count - 1; } else { return 0; } } @Override public int getDiscussionMessagesCount( String className, long classPK, int status) { long classNameId = classNameLocalService.getClassNameId(className); return getDiscussionMessagesCount(classNameId, classPK, status); } @Override public List<MBDiscussion> getDiscussions(String className) { long classNameId = classNameLocalService.getClassNameId(className); return mbDiscussionPersistence.findByClassNameId(classNameId); } @Override public List<MBMessage> getGroupMessages( long groupId, int status, int start, int end) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.findByGroupId(groupId, start, end); } else { return mbMessagePersistence.findByG_S(groupId, status, start, end); } } @Override public List<MBMessage> getGroupMessages( long groupId, int status, int start, int end, OrderByComparator<MBMessage> obc) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.findByGroupId(groupId, start, end, obc); } else { return mbMessagePersistence.findByG_S( groupId, status, start, end, obc); } } @Override public List<MBMessage> getGroupMessages( long groupId, long userId, int status, int start, int end) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.findByG_U(groupId, userId, start, end); } else { return mbMessagePersistence.findByG_U_S( groupId, userId, status, start, end); } } @Override public List<MBMessage> getGroupMessages( long groupId, long userId, int status, int start, int end, OrderByComparator<MBMessage> obc) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.findByG_U( groupId, userId, start, end, obc); } else { return mbMessagePersistence.findByG_U_S( groupId, userId, status, start, end, obc); } } @Override public int getGroupMessagesCount(long groupId, int status) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.countByGroupId(groupId); } else { return mbMessagePersistence.countByG_S(groupId, status); } } @Override public int getGroupMessagesCount(long groupId, long userId, int status) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.countByG_U(groupId, userId); } else { return mbMessagePersistence.countByG_U_S(groupId, userId, status); } } @Override public MBMessage getMessage(long messageId) throws PortalException { return mbMessagePersistence.findByPrimaryKey(messageId); } @Override public MBMessageDisplay getMessageDisplay( long userId, long messageId, int status) throws PortalException { MBMessage message = getMessage(messageId); return getMessageDisplay(userId, message, status); } /** * @deprecated As of 7.0.0, replaced by {@link #getMessageDisplay(long, * long, int)} */ @Deprecated @Override public MBMessageDisplay getMessageDisplay( long userId, long messageId, int status, String threadView, boolean includePrevAndNext) throws PortalException { MBMessage message = getMessage(messageId); return getMessageDisplay( userId, message, status, threadView, includePrevAndNext); } @Override public MBMessageDisplay getMessageDisplay( long userId, MBMessage message, int status) throws PortalException { return getMessageDisplay( userId, message, status, new MessageThreadComparator()); } @Override public MBMessageDisplay getMessageDisplay( long userId, MBMessage message, int status, Comparator<MBMessage> comparator) throws PortalException { MBCategory category = null; if ((message.getCategoryId() != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) && (message.getCategoryId() != MBCategoryConstants.DISCUSSION_CATEGORY_ID)) { category = mbCategoryPersistence.findByPrimaryKey( message.getCategoryId()); } else { category = new MBCategoryImpl(); category.setCategoryId(message.getCategoryId()); category.setDisplayStyle(MBCategoryConstants.DEFAULT_DISPLAY_STYLE); } MBMessage parentMessage = null; if (message.isReply()) { parentMessage = mbMessagePersistence.findByPrimaryKey( message.getParentMessageId()); } MBThread thread = mbThreadPersistence.findByPrimaryKey( message.getThreadId()); if (message.isApproved() && !message.isDiscussion()) { mbThreadLocalService.incrementViewCounter(thread.getThreadId(), 1); SocialActivityManagerUtil.addActivity( userId, thread, SocialActivityConstants.TYPE_VIEW, StringPool.BLANK, 0); } return new MBMessageDisplayImpl( userId, message, parentMessage, category, thread, status, this, comparator); } /** * @deprecated As of 7.0.0, replaced by {@link #getMessageDisplay(long, * MBMessage, int)} */ @Deprecated @Override public MBMessageDisplay getMessageDisplay( long userId, MBMessage message, int status, String threadView, boolean includePrevAndNext) throws PortalException { return getMessageDisplay( userId, message, status, threadView, includePrevAndNext, new MessageThreadComparator()); } /** * @deprecated As of 7.0.0, replaced by {@link #getMessageDisplay(long, * MBMessage, int, Comparator)} ( */ @Deprecated @Override public MBMessageDisplay getMessageDisplay( long userId, MBMessage message, int status, String threadView, boolean includePrevAndNext, Comparator<MBMessage> comparator) throws PortalException { MBMessageDisplay messageDisplay = getMessageDisplay( userId, message, status, comparator); return new MBMessageDisplayImpl( messageDisplay.getMessage(), messageDisplay.getParentMessage(), messageDisplay.getCategory(), messageDisplay.getThread(), null, null, status, threadView, this, comparator); } @Override public List<MBMessage> getMessages( String className, long classPK, int status) { long classNameId = classNameLocalService.getClassNameId(className); if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.findByC_C(classNameId, classPK); } else { return mbMessagePersistence.findByC_C_S( classNameId, classPK, status); } } @Override public List<MBMessage> getNoAssetMessages() { return mbMessageFinder.findByNoAssets(); } @Override public int getPositionInThread(long messageId) throws PortalException { MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId); return mbMessageFinder.countByC_T( message.getCreateDate(), message.getThreadId()); } @Override public List<MBMessage> getThreadMessages(long threadId, int status) { return getThreadMessages( threadId, status, new MessageThreadComparator()); } @Override public List<MBMessage> getThreadMessages( long threadId, int status, Comparator<MBMessage> comparator) { List<MBMessage> messages = null; if (status == WorkflowConstants.STATUS_ANY) { messages = mbMessagePersistence.findByThreadId(threadId); } else { messages = mbMessagePersistence.findByT_S(threadId, status); } return ListUtil.sort(messages, comparator); } @Override public List<MBMessage> getThreadMessages( long threadId, int status, int start, int end) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.findByThreadId(threadId, start, end); } else { return mbMessagePersistence.findByT_S(threadId, status, start, end); } } @Override public List<MBMessage> getThreadMessages( long userId, long threadId, int status, int start, int end, Comparator<MBMessage> comparator) { QueryDefinition<MBMessage> queryDefinition = new QueryDefinition<>( status, userId, true, start, end, null); if (comparator instanceof OrderByComparator) { queryDefinition.setOrderByComparator( (OrderByComparator<MBMessage>)comparator); } List<MBMessage> messages = mbMessageFinder.findByThreadId( threadId, queryDefinition); if (!(comparator instanceof OrderByComparator)) { messages = ListUtil.sort(messages, comparator); } return messages; } @Override public int getThreadMessagesCount(long threadId, int status) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.countByThreadId(threadId); } else { return mbMessagePersistence.countByT_S(threadId, status); } } @Override public List<MBMessage> getThreadRepliesMessages( long threadId, int status, int start, int end) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.findByThreadReplies( threadId, start, end); } else { return mbMessagePersistence.findByTR_S( threadId, status, start, end); } } @Override public List<MBMessage> getUserDiscussionMessages( long userId, long classNameId, long classPK, int status, int start, int end, OrderByComparator<MBMessage> obc) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.findByU_C_C( userId, classNameId, classPK, start, end, obc); } else { return mbMessagePersistence.findByU_C_C_S( userId, classNameId, classPK, status, start, end, obc); } } @Override public List<MBMessage> getUserDiscussionMessages( long userId, long[] classNameIds, int status, int start, int end, OrderByComparator<MBMessage> obc) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.findByU_C( userId, classNameIds, start, end, obc); } else { return mbMessagePersistence.findByU_C_S( userId, classNameIds, status, start, end, obc); } } @Override public List<MBMessage> getUserDiscussionMessages( long userId, String className, long classPK, int status, int start, int end, OrderByComparator<MBMessage> obc) { long classNameId = classNameLocalService.getClassNameId(className); return getUserDiscussionMessages( userId, classNameId, classPK, status, start, end, obc); } @Override public int getUserDiscussionMessagesCount( long userId, long classNameId, long classPK, int status) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.countByU_C_C( userId, classNameId, classPK); } else { return mbMessagePersistence.countByU_C_C_S( userId, classNameId, classPK, status); } } @Override public int getUserDiscussionMessagesCount( long userId, long[] classNameIds, int status) { if (status == WorkflowConstants.STATUS_ANY) { return mbMessagePersistence.countByU_C(userId, classNameIds); } else { return mbMessagePersistence.countByU_C_S( userId, classNameIds, status); } } @Override public int getUserDiscussionMessagesCount( long userId, String className, long classPK, int status) { long classNameId = classNameLocalService.getClassNameId(className); return getUserDiscussionMessagesCount( userId, classNameId, classPK, status); } @Override public long moveMessageAttachmentToTrash( long userId, long messageId, String fileName) throws PortalException { MBMessage message = getMessage(messageId); long folderId = message.getAttachmentsFolderId(); FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry( message.getGroupId(), folderId, fileName); PortletFileRepositoryUtil.movePortletFileEntryToTrash( userId, fileEntry.getFileEntryId()); return fileEntry.getFileEntryId(); } @Override public void restoreMessageAttachmentFromTrash( long userId, long messageId, String deletedFileName) throws PortalException { MBMessage message = getMessage(messageId); Folder folder = message.addAttachmentsFolder(); PortletFileRepositoryUtil.restorePortletFileEntryFromTrash( message.getGroupId(), userId, folder.getFolderId(), deletedFileName); } @Override public void subscribeMessage(long userId, long messageId) throws PortalException { } @Override public void unsubscribeMessage(long userId, long messageId) throws PortalException { } @Override public void updateAnswer(long messageId, boolean answer, boolean cascade) throws PortalException { MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId); updateAnswer(message, answer, cascade); } @Override public void updateAnswer(MBMessage message, boolean answer, boolean cascade) throws PortalException { if (message.isAnswer() != answer) { message.setAnswer(answer); mbMessagePersistence.update(message); } if (cascade) { List<MBMessage> messages = mbMessagePersistence.findByT_P( message.getThreadId(), message.getMessageId()); for (MBMessage curMessage : messages) { updateAnswer(curMessage, answer, cascade); } } } @Override public void updateAsset( long userId, MBMessage message, long[] assetCategoryIds, String[] assetTagNames, long[] assetLinkEntryIds) throws PortalException { updateAsset( userId, message, assetCategoryIds, assetTagNames, assetLinkEntryIds, true); } @Override public MBMessage updateDiscussionMessage( long userId, long messageId, String className, long classPK, String subject, String body, ServiceContext serviceContext) throws PortalException { subject = getDiscussionMessageSubject(subject, body); List<ObjectValuePair<String, InputStream>> inputStreamOVPs = null; List<String> existingFiles = null; double priority = 0.0; boolean allowPingbacks = false; serviceContext.setAttribute("className", className); serviceContext.setAttribute("classPK", String.valueOf(classPK)); return updateMessage( userId, messageId, subject, body, inputStreamOVPs, existingFiles, priority, allowPingbacks, serviceContext); } @Override public MBMessage updateMessage( long userId, long messageId, String body, ServiceContext serviceContext) throws PortalException { MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId); return updateMessage( userId, messageId, message.getSubject(), body, null, null, message.getPriority(), message.isAllowPingbacks(), serviceContext); } @Override public MBMessage updateMessage( long userId, long messageId, String subject, String body, List<ObjectValuePair<String, InputStream>> inputStreamOVPs, List<String> existingFiles, double priority, boolean allowPingbacks, ServiceContext serviceContext) throws PortalException { // Message MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId); int oldStatus = message.getStatus(); Date modifiedDate = serviceContext.getModifiedDate(null); subject = ModelHintsUtil.trimString( MBMessage.class.getName(), "subject", subject); subject = getSubject(subject, body); body = getBody(subject, body); Map<String, Object> options = new HashMap<>(); options.put("discussion", message.isDiscussion()); body = SanitizerUtil.sanitize( message.getCompanyId(), message.getGroupId(), userId, MBMessage.class.getName(), messageId, "text/" + message.getFormat(), Sanitizer.MODE_ALL, body, options); validate(subject, body); message.setModifiedDate(modifiedDate); message.setSubject(subject); message.setBody(body); message.setAllowPingbacks(allowPingbacks); if (priority != MBThreadConstants.PRIORITY_NOT_GIVEN) { message.setPriority(priority); } MBThread thread = mbThreadPersistence.findByPrimaryKey( message.getThreadId()); if (serviceContext.getWorkflowAction() == WorkflowConstants.ACTION_SAVE_DRAFT) { if (!message.isDraft() && !message.isPending()) { message.setStatus(WorkflowConstants.STATUS_DRAFT); // Thread User user = userPersistence.findByPrimaryKey(userId); updateThreadStatus( thread, message, user, oldStatus, modifiedDate); // Asset assetEntryLocalService.updateVisible( message.getWorkflowClassName(), message.getMessageId(), false); if (!message.isDiscussion()) { // Indexer Indexer<MBMessage> indexer = IndexerRegistryUtil.nullSafeGetIndexer(MBMessage.class); indexer.delete(message); } } } // Attachments if ((inputStreamOVPs != null) || (existingFiles != null)) { if (ListUtil.isNotEmpty(inputStreamOVPs) || ListUtil.isNotEmpty(existingFiles)) { List<FileEntry> fileEntries = message.getAttachmentsFileEntries(); for (FileEntry fileEntry : fileEntries) { String fileEntryId = String.valueOf( fileEntry.getFileEntryId()); if (!existingFiles.contains(fileEntryId)) { if (!TrashUtil.isTrashEnabled(message.getGroupId())) { deleteMessageAttachment( messageId, fileEntry.getTitle()); } else { moveMessageAttachmentToTrash( userId, messageId, fileEntry.getTitle()); } } } Folder folder = message.addAttachmentsFolder(); PortletFileRepositoryUtil.addPortletFileEntries( message.getGroupId(), userId, MBMessage.class.getName(), message.getMessageId(), MBConstants.SERVICE_NAME, folder.getFolderId(), inputStreamOVPs); } else { if (TrashUtil.isTrashEnabled(message.getGroupId())) { List<FileEntry> fileEntries = message.getAttachmentsFileEntries(); for (FileEntry fileEntry : fileEntries) { moveMessageAttachmentToTrash( userId, messageId, fileEntry.getTitle()); } } else { deleteMessageAttachments(message.getMessageId()); } } } message.setExpandoBridgeAttributes(serviceContext); mbMessagePersistence.update(message); // Statistics if ((serviceContext.getWorkflowAction() == WorkflowConstants.ACTION_SAVE_DRAFT) && !message.isDiscussion()) { mbStatsUserLocalService.updateStatsUser( message.getGroupId(), userId, message.getModifiedDate()); } // Thread if ((priority != MBThreadConstants.PRIORITY_NOT_GIVEN) && (thread.getPriority() != priority)) { thread.setPriority(priority); mbThreadPersistence.update(thread); updatePriorities(thread.getThreadId(), priority); } // Asset updateAsset( userId, message, serviceContext.getAssetCategoryIds(), serviceContext.getAssetTagNames(), serviceContext.getAssetLinkEntryIds()); // Workflow startWorkflowInstance(userId, message, serviceContext); return message; } /** * @deprecated As of 7.0.0, with no direct replacement */ @Deprecated @Override public MBMessage updateMessage(long messageId, String body) throws PortalException { MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId); message.setBody(body); mbMessagePersistence.update(message); return message; } /** * @deprecated As of 7.0.0, replaced by {@link #updateStatus(long, long, * int, ServiceContext, Map)} */ @Deprecated @Override public MBMessage updateStatus( long userId, long messageId, int status, ServiceContext serviceContext) throws PortalException { return updateStatus( userId, messageId, status, serviceContext, new HashMap<String, Serializable>()); } @Override public MBMessage updateStatus( long userId, long messageId, int status, ServiceContext serviceContext, Map<String, Serializable> workflowContext) throws PortalException { // Message MBMessage message = getMessage(messageId); int oldStatus = message.getStatus(); User user = userPersistence.findByPrimaryKey(userId); Date now = new Date(); Date modifiedDate = serviceContext.getModifiedDate(now); message.setStatus(status); message.setStatusByUserId(userId); message.setStatusByUserName(user.getFullName()); message.setStatusDate(modifiedDate); mbMessagePersistence.update(message); // Thread MBThread thread = mbThreadPersistence.findByPrimaryKey( message.getThreadId()); updateThreadStatus(thread, message, user, oldStatus, modifiedDate); Indexer<MBMessage> indexer = IndexerRegistryUtil.nullSafeGetIndexer( MBMessage.class); if (status == WorkflowConstants.STATUS_APPROVED) { if (oldStatus != WorkflowConstants.STATUS_APPROVED) { // Asset if (serviceContext.isAssetEntryVisible() && ((message.getClassNameId() == 0) || (message.getParentMessageId() != 0))) { Date publishDate = null; AssetEntry assetEntry = assetEntryLocalService.fetchEntry( message.getWorkflowClassName(), message.getMessageId()); if ((assetEntry != null) && (assetEntry.getPublishDate() != null)) { publishDate = assetEntry.getPublishDate(); } else { publishDate = now; serviceContext.setCommand(Constants.ADD); } assetEntryLocalService.updateEntry( message.getWorkflowClassName(), message.getMessageId(), publishDate, null, true, true); } if (serviceContext.isCommandAdd()) { // Social JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject(); String title = message.getSubject(); if (message.isDiscussion()) { title = HtmlUtil.stripHtml(title); } extraDataJSONObject.put("title", title); if (!message.isDiscussion()) { if (!message.isAnonymous() && !user.isDefaultUser()) { long receiverUserId = 0; MBMessage parentMessage = mbMessagePersistence.fetchByPrimaryKey( message.getParentMessageId()); if (parentMessage != null) { receiverUserId = parentMessage.getUserId(); } SocialActivityManagerUtil.addActivity( message.getUserId(), message, MBActivityKeys.ADD_MESSAGE, extraDataJSONObject.toString(), receiverUserId); if ((parentMessage != null) && (receiverUserId != message.getUserId())) { SocialActivityManagerUtil.addActivity( message.getUserId(), parentMessage, MBActivityKeys.REPLY_MESSAGE, extraDataJSONObject.toString(), 0); } } } else { String className = (String)serviceContext.getAttribute( "className"); long classPK = ParamUtil.getLong( serviceContext, "classPK"); long parentMessageId = message.getParentMessageId(); if (parentMessageId != MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID) { AssetEntry assetEntry = assetEntryLocalService.fetchEntry( className, classPK); if (assetEntry != null) { extraDataJSONObject.put( "messageId", message.getMessageId()); SocialActivityManagerUtil.addActivity( message.getUserId(), assetEntry, SocialActivityConstants.TYPE_ADD_COMMENT, extraDataJSONObject.toString(), assetEntry.getUserId()); } } } } } // Indexer indexer.reindex(message); // Ping pingPingback(message, serviceContext); } else if (oldStatus == WorkflowConstants.STATUS_APPROVED) { // Asset assetEntryLocalService.updateVisible( message.getWorkflowClassName(), message.getMessageId(), false); // Indexer indexer.delete(message); } // Statistics if (!message.isDiscussion()) { mbStatsUserLocalService.updateStatsUser( message.getGroupId(), userId, serviceContext.getModifiedDate(now)); } return message; } @Override public void updateUserName(long userId, String userName) { List<MBMessage> messages = mbMessagePersistence.findByUserId(userId); for (MBMessage message : messages) { message.setUserName(userName); mbMessagePersistence.update(message); } } protected String getBody(String subject, String body) { if (Validator.isNull(body)) { return subject; } return body; } protected String getDiscussionMessageSubject(String subject, String body) throws MessageBodyException { if (Validator.isNotNull(subject)) { return subject; } if (Validator.isNull(body)) { throw new MessageBodyException("Body is null"); } subject = HtmlUtil.extractText(body); if (subject.length() <= MBMessageConstants.MESSAGE_SUBJECT_MAX_LENGTH) { return subject; } String subjectSubstring = subject.substring( 0, MBMessageConstants.MESSAGE_SUBJECT_MAX_LENGTH); return subjectSubstring + StringPool.TRIPLE_PERIOD; } protected String getMessageURL( MBMessage message, ServiceContext serviceContext) throws PortalException { String entryURL = GetterUtil.getString( serviceContext.getAttribute("entryURL")); if (Validator.isNotNull(entryURL)) { return entryURL; } HttpServletRequest request = serviceContext.getRequest(); if (request == null) { if (Validator.isNull(serviceContext.getLayoutFullURL())) { return StringPool.BLANK; } return serviceContext.getLayoutFullURL() + Portal.FRIENDLY_URL_SEPARATOR + "message_boards/view_message/" + message.getMessageId(); } String portletId = PortletProviderUtil.getPortletId( MBMessage.class.getName(), PortletProvider.Action.VIEW); String layoutURL = LayoutURLUtil.getLayoutURL( message.getGroupId(), portletId, serviceContext); if (Validator.isNotNull(layoutURL)) { return layoutURL + Portal.FRIENDLY_URL_SEPARATOR + "message_boards/view_message/" + message.getMessageId(); } else { Group group = groupLocalService.fetchGroup(message.getGroupId()); portletId = PortletProviderUtil.getPortletId( MBMessage.class.getName(), PortletProvider.Action.MANAGE); PortletURL portletURL = PortalUtil.getControlPanelPortletURL( request, group, portletId, 0, 0, PortletRequest.RENDER_PHASE); portletURL.setParameter( "mvcRenderCommandName", "/message_boards/view_message"); portletURL.setParameter( "messageId", String.valueOf(message.getMessageId())); return portletURL.toString(); } } protected String getSubject(String subject, String body) { if (Validator.isNull(subject)) { return StringUtil.shorten(body); } return subject; } /** * @deprecated As of 7.0.0, with no direct replacement */ @Deprecated protected MBSubscriptionSender getSubscriptionSender( long userId, MBCategory category, MBMessage message, String messageURL, String entryTitle, boolean htmlFormat, String messageBody, String messageSubject, String messageSubjectPrefix, String inReplyTo, String fromName, String fromAddress, String replyToAddress, String emailAddress, String fullName, LocalizedValuesMap subjectLocalizedValuesMap, LocalizedValuesMap bodyLocalizedValuesMap, ServiceContext serviceContext) { return null; } /** * @deprecated As of 7.0.0, with no direct replacement */ @Deprecated protected void notifyDiscussionSubscribers( long userId, MBMessage message, ServiceContext serviceContext) throws PortalException { } /** * @deprecated As of 7.0.0, with no direct replacement */ @Deprecated protected void notifySubscribers( long userId, MBMessage message, String messageURL, ServiceContext serviceContext) throws PortalException { } protected void pingPingback( MBMessage message, ServiceContext serviceContext) { if (!PropsValues.BLOGS_PINGBACK_ENABLED || !message.isAllowPingbacks() || !message.isApproved()) { return; } String layoutFullURL = serviceContext.getLayoutFullURL(); if (Validator.isNull(layoutFullURL)) { return; } String sourceUri = layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "message_boards/view_message/" + message.getMessageId(); Source source = new Source(message.getBody(message.isFormatBBCode())); List<StartTag> startTags = source.getAllStartTags("a"); for (StartTag startTag : startTags) { String targetUri = startTag.getAttributeValue("href"); if (Validator.isNotNull(targetUri)) { try { LinkbackProducerUtil.sendPingback(sourceUri, targetUri); } catch (Exception e) { _log.error("Error while sending pingback " + targetUri, e); } } } } protected void startWorkflowInstance( long userId, MBMessage message, ServiceContext serviceContext) throws PortalException { Map<String, Serializable> workflowContext = new HashMap<>(); workflowContext.put( WorkflowConstants.CONTEXT_URL, getMessageURL(message, serviceContext)); WorkflowHandlerRegistryUtil.startWorkflowInstance( message.getCompanyId(), message.getGroupId(), userId, message.getWorkflowClassName(), message.getMessageId(), message, serviceContext, workflowContext); } protected void updateAsset( long userId, MBMessage message, long[] assetCategoryIds, String[] assetTagNames, long[] assetLinkEntryIds, boolean assetEntryVisible) throws PortalException { boolean visible = false; Date publishDate = null; if (assetEntryVisible && message.isApproved() && ((message.getClassNameId() == 0) || (message.getParentMessageId() != 0))) { visible = true; publishDate = message.getModifiedDate(); } AssetEntry assetEntry = assetEntryLocalService.updateEntry( userId, message.getGroupId(), message.getCreateDate(), message.getModifiedDate(), message.getWorkflowClassName(), message.getMessageId(), message.getUuid(), 0, assetCategoryIds, assetTagNames, true, visible, null, null, publishDate, null, ContentTypes.TEXT_HTML, message.getSubject(), null, null, null, null, 0, 0, message.getPriority()); assetLinkLocalService.updateLinks( userId, assetEntry.getEntryId(), assetLinkEntryIds, AssetLinkConstants.TYPE_RELATED); } protected void updatePriorities(long threadId, double priority) { List<MBMessage> messages = mbMessagePersistence.findByThreadId( threadId); for (MBMessage message : messages) { if (message.getPriority() != priority) { message.setPriority(priority); mbMessagePersistence.update(message); } } } protected void updateThreadStatus( MBThread thread, MBMessage message, User user, int oldStatus, Date modifiedDate) throws PortalException { MBCategory category = null; int status = message.getStatus(); if ((thread.getCategoryId() != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) && (thread.getCategoryId() != MBCategoryConstants.DISCUSSION_CATEGORY_ID)) { category = mbCategoryPersistence.findByPrimaryKey( thread.getCategoryId()); } if ((thread.getRootMessageId() == message.getMessageId()) && (oldStatus != status)) { thread.setModifiedDate(modifiedDate); thread.setStatus(status); thread.setStatusByUserId(user.getUserId()); thread.setStatusByUserName(user.getFullName()); thread.setStatusDate(modifiedDate); } if (status == oldStatus) { return; } if (status == WorkflowConstants.STATUS_APPROVED) { if (message.isAnonymous()) { thread.setLastPostByUserId(0); } else { thread.setLastPostByUserId(message.getUserId()); } thread.setLastPostDate(modifiedDate); if (category != null) { category.setLastPostDate(modifiedDate); category = mbCategoryPersistence.update(category); } } if ((oldStatus == WorkflowConstants.STATUS_APPROVED) || (status == WorkflowConstants.STATUS_APPROVED)) { // Thread MBUtil.updateThreadMessageCount(thread.getThreadId()); // Category if ((category != null) && (thread.getRootMessageId() == message.getMessageId())) { MBUtil.updateCategoryStatistics(category.getCategoryId()); } if ((category != null) && !(thread.getRootMessageId() == message.getMessageId())) { MBUtil.updateCategoryMessageCount(category.getCategoryId()); } } // Indexer Indexer<MBThread> indexer = IndexerRegistryUtil.nullSafeGetIndexer( MBThread.class); indexer.reindex(thread); mbThreadPersistence.update(thread); } protected void validate(String subject, String body) throws PortalException { if (Validator.isNull(subject) && Validator.isNull(body)) { throw new MessageSubjectException("Subject and body are null"); } } protected void validateDiscussionMaxComments(String className, long classPK) throws PortalException { if (PropsValues.DISCUSSION_MAX_COMMENTS <= 0) { return; } int count = getDiscussionMessagesCount( className, classPK, WorkflowConstants.STATUS_APPROVED); if (count >= PropsValues.DISCUSSION_MAX_COMMENTS) { int max = PropsValues.DISCUSSION_MAX_COMMENTS - 1; throw new DiscussionMaxCommentsException(count + " exceeds " + max); } } private static final Log _log = LogFactoryUtil.getLog( MBMessageLocalServiceImpl.class); }