/** * 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.document.library.kernel.model.DLFolderConstants; import com.liferay.exportimport.kernel.lar.ExportImportThreadLocal; import com.liferay.message.boards.kernel.constants.MBConstants; import com.liferay.message.boards.kernel.exception.NoSuchCategoryException; import com.liferay.message.boards.kernel.exception.SplitThreadException; import com.liferay.message.boards.kernel.model.MBCategory; import com.liferay.message.boards.kernel.model.MBCategoryConstants; 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.model.MBTreeWalker; import com.liferay.portal.kernel.dao.orm.QueryDefinition; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.increment.BufferedIncrement; import com.liferay.portal.kernel.increment.NumberIncrement; import com.liferay.portal.kernel.json.JSONFactoryUtil; import com.liferay.portal.kernel.json.JSONObject; import com.liferay.portal.kernel.model.Group; 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.portletfilerepository.PortletFileRepositoryUtil; import com.liferay.portal.kernel.repository.model.FileEntry; import com.liferay.portal.kernel.repository.model.Folder; import com.liferay.portal.kernel.search.Field; import com.liferay.portal.kernel.search.Hits; import com.liferay.portal.kernel.search.Indexer; import com.liferay.portal.kernel.search.IndexerRegistryUtil; import com.liferay.portal.kernel.search.SearchContext; import com.liferay.portal.kernel.search.Sort; import com.liferay.portal.kernel.service.ServiceContext; import com.liferay.portal.kernel.social.SocialActivityManagerUtil; import com.liferay.portal.kernel.systemevent.SystemEvent; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.kernel.util.Validator; import com.liferay.portal.kernel.workflow.WorkflowConstants; import com.liferay.portlet.messageboards.service.base.MBThreadLocalServiceBaseImpl; import com.liferay.portlet.messageboards.util.MBUtil; import com.liferay.social.kernel.model.SocialActivityConstants; import com.liferay.trash.kernel.exception.RestoreEntryException; import com.liferay.trash.kernel.exception.TrashEntryException; import com.liferay.trash.kernel.model.TrashEntry; import com.liferay.trash.kernel.model.TrashVersion; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; /** * @author Brian Wing Shun Chan * @author Shuyang Zhou */ public class MBThreadLocalServiceImpl extends MBThreadLocalServiceBaseImpl { @Override public MBThread addThread( long categoryId, MBMessage message, ServiceContext serviceContext) throws PortalException { // Thread long threadId = message.getThreadId(); if (!message.isRoot() || (threadId <= 0)) { threadId = counterLocalService.increment(); } MBThread thread = mbThreadPersistence.create(threadId); thread.setUuid(serviceContext.getUuid()); thread.setGroupId(message.getGroupId()); thread.setCompanyId(message.getCompanyId()); thread.setUserId(message.getUserId()); thread.setUserName(message.getUserName()); thread.setCategoryId(categoryId); thread.setRootMessageId(message.getMessageId()); thread.setRootMessageUserId(message.getUserId()); if (message.isAnonymous()) { thread.setLastPostByUserId(0); } else { thread.setLastPostByUserId(message.getUserId()); } thread.setLastPostDate(message.getModifiedDate()); if (message.getPriority() != MBThreadConstants.PRIORITY_NOT_GIVEN) { thread.setPriority(message.getPriority()); } thread.setStatus(message.getStatus()); thread.setStatusByUserId(message.getStatusByUserId()); thread.setStatusByUserName(message.getStatusByUserName()); thread.setStatusDate(message.getStatusDate()); mbThreadPersistence.update(thread); // Asset if (categoryId >= 0) { assetEntryLocalService.updateEntry( message.getUserId(), message.getGroupId(), thread.getStatusDate(), thread.getLastPostDate(), MBThread.class.getName(), thread.getThreadId(), thread.getUuid(), 0, new long[0], new String[0], true, false, null, null, thread.getStatusDate(), null, null, String.valueOf(thread.getRootMessageId()), null, null, null, null, 0, 0, serviceContext.getAssetPriority()); } return thread; } @Override public void deleteThread(long threadId) throws PortalException { MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId); mbThreadLocalService.deleteThread(thread); } @Override @SystemEvent( action = SystemEventConstants.ACTION_SKIP, type = SystemEventConstants.TYPE_DELETE ) public void deleteThread(MBThread thread) throws PortalException { MBMessage rootMessage = mbMessagePersistence.findByPrimaryKey( thread.getRootMessageId()); // Indexer Indexer<MBMessage> messageIndexer = IndexerRegistryUtil.nullSafeGetIndexer(MBMessage.class); // Attachments long folderId = thread.getAttachmentsFolderId(); if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) { PortletFileRepositoryUtil.deletePortletFolder(folderId); } // Thread flags mbThreadFlagLocalService.deleteThreadFlagsByThreadId( thread.getThreadId()); // Messages List<MBMessage> messages = mbMessagePersistence.findByThreadId( thread.getThreadId()); for (MBMessage message : messages) { // Ratings ratingsStatsLocalService.deleteStats( message.getWorkflowClassName(), message.getMessageId()); // Asset assetEntryLocalService.deleteEntry( message.getWorkflowClassName(), message.getMessageId()); // Resources if (!message.isDiscussion()) { resourceLocalService.deleteResource( message.getCompanyId(), message.getWorkflowClassName(), ResourceConstants.SCOPE_INDIVIDUAL, message.getMessageId()); } // Message mbMessagePersistence.remove(message); // Indexer messageIndexer.delete(message); // Statistics if (!message.isDiscussion()) { mbStatsUserLocalService.updateStatsUser( message.getGroupId(), message.getUserId()); } // Workflow workflowInstanceLinkLocalService.deleteWorkflowInstanceLink( message.getCompanyId(), message.getGroupId(), message.getWorkflowClassName(), message.getMessageId()); } // Category if ((rootMessage.getCategoryId() != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) && (rootMessage.getCategoryId() != MBCategoryConstants.DISCUSSION_CATEGORY_ID)) { try { MBCategory category = mbCategoryPersistence.findByPrimaryKey( thread.getCategoryId()); MBUtil.updateCategoryStatistics(category.getCategoryId()); } catch (NoSuchCategoryException nsce) { if (!thread.isInTrash()) { throw nsce; } } } // Asset AssetEntry assetEntry = assetEntryLocalService.fetchEntry( MBThread.class.getName(), thread.getThreadId()); if (assetEntry != null) { assetEntry.setTitle(rootMessage.getSubject()); assetEntryLocalService.updateAssetEntry(assetEntry); } assetEntryLocalService.deleteEntry( MBThread.class.getName(), thread.getThreadId()); // Trash if (thread.isInTrashExplicitly()) { trashEntryLocalService.deleteEntry( MBThread.class.getName(), thread.getThreadId()); } else { trashVersionLocalService.deleteTrashVersion( MBThread.class.getName(), thread.getThreadId()); } // Indexer Indexer<MBThread> threadIndexer = IndexerRegistryUtil.nullSafeGetIndexer(MBThread.class); threadIndexer.delete(thread); // Thread mbThreadPersistence.remove(thread); } @Override public void deleteThreads(long groupId, long categoryId) throws PortalException { deleteThreads(groupId, categoryId, true); } @Override public void deleteThreads( long groupId, long categoryId, boolean includeTrashedEntries) throws PortalException { List<MBThread> threads = mbThreadPersistence.findByG_C( groupId, categoryId); for (MBThread thread : threads) { if (includeTrashedEntries || !thread.isInTrashExplicitly()) { mbThreadLocalService.deleteThread(thread); } } if (mbThreadPersistence.countByGroupId(groupId) == 0) { PortletFileRepositoryUtil.deletePortletRepository( groupId, MBConstants.SERVICE_NAME); } } @Override public MBThread fetchThread(long threadId) { return mbThreadPersistence.fetchByPrimaryKey(threadId); } @Override public int getCategoryThreadsCount( long groupId, long categoryId, int status) { if (status == WorkflowConstants.STATUS_ANY) { return mbThreadPersistence.countByG_C(groupId, categoryId); } else { return mbThreadPersistence.countByG_C_S( groupId, categoryId, status); } } @Override public List<MBThread> getGroupThreads( long groupId, long userId, boolean subscribed, boolean includeAnonymous, QueryDefinition<MBThread> queryDefinition) { if (userId <= 0) { return getGroupThreads(groupId, queryDefinition); } if (subscribed) { return mbThreadFinder.findByS_G_U_C( groupId, userId, null, queryDefinition); } else { if (includeAnonymous) { return mbThreadFinder.findByG_U_C( groupId, userId, null, queryDefinition); } else { return mbThreadFinder.findByG_U_C_A( groupId, userId, null, false, queryDefinition); } } } @Override public List<MBThread> getGroupThreads( long groupId, long userId, boolean subscribed, QueryDefinition<MBThread> queryDefinition) { return getGroupThreads( groupId, userId, subscribed, true, queryDefinition); } @Override public List<MBThread> getGroupThreads( long groupId, long userId, QueryDefinition<MBThread> queryDefinition) { return getGroupThreads(groupId, userId, false, queryDefinition); } @Override public List<MBThread> getGroupThreads( long groupId, QueryDefinition<MBThread> queryDefinition) { if (queryDefinition.isExcludeStatus()) { return mbThreadPersistence.findByG_NotC_NotS( groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, queryDefinition.getStatus(), queryDefinition.getStart(), queryDefinition.getEnd()); } else { return mbThreadPersistence.findByG_NotC_S( groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, queryDefinition.getStatus(), queryDefinition.getStart(), queryDefinition.getEnd()); } } @Override public int getGroupThreadsCount( long groupId, long userId, boolean subscribed, boolean includeAnonymous, QueryDefinition<MBThread> queryDefinition) { if (userId <= 0) { return getGroupThreadsCount(groupId, queryDefinition); } if (subscribed) { return mbThreadFinder.countByS_G_U_C( groupId, userId, null, queryDefinition); } else { if (includeAnonymous) { return mbThreadFinder.countByG_U_C( groupId, userId, null, queryDefinition); } else { return mbThreadFinder.countByG_U_C_A( groupId, userId, null, false, queryDefinition); } } } @Override public int getGroupThreadsCount( long groupId, long userId, boolean subscribed, QueryDefinition<MBThread> queryDefinition) { return getGroupThreadsCount( groupId, userId, subscribed, true, queryDefinition); } @Override public int getGroupThreadsCount( long groupId, long userId, QueryDefinition<MBThread> queryDefinition) { return getGroupThreadsCount(groupId, userId, false, queryDefinition); } @Override public int getGroupThreadsCount( long groupId, QueryDefinition<MBThread> queryDefinition) { if (queryDefinition.isExcludeStatus()) { return mbThreadPersistence.countByG_NotC_NotS( groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, queryDefinition.getStatus()); } else { return mbThreadPersistence.countByG_NotC_S( groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID, queryDefinition.getStatus()); } } @Override public List<MBThread> getNoAssetThreads() { return mbThreadFinder.findByNoAssets(); } @Override public List<MBThread> getPriorityThreads(long categoryId, double priority) throws PortalException { return getPriorityThreads(categoryId, priority, false); } @Override public List<MBThread> getPriorityThreads( long categoryId, double priority, boolean inherit) throws PortalException { if (!inherit) { return mbThreadPersistence.findByC_P(categoryId, priority); } List<MBThread> threads = new ArrayList<>(); while ((categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) && (categoryId != MBCategoryConstants.DISCUSSION_CATEGORY_ID)) { threads.addAll( 0, mbThreadPersistence.findByC_P(categoryId, priority)); MBCategory category = mbCategoryPersistence.findByPrimaryKey( categoryId); categoryId = category.getParentCategoryId(); } return threads; } @Override public MBThread getThread(long threadId) throws PortalException { return mbThreadPersistence.findByPrimaryKey(threadId); } @Override public List<MBThread> getThreads( long groupId, long categoryId, int status, int start, int end) { if (status == WorkflowConstants.STATUS_ANY) { return mbThreadPersistence.findByG_C( groupId, categoryId, start, end); } else { return mbThreadPersistence.findByG_C_S( groupId, categoryId, status, start, end); } } @Override public int getThreadsCount(long groupId, long categoryId, int status) { if (status == WorkflowConstants.STATUS_ANY) { return mbThreadPersistence.countByG_C(groupId, categoryId); } else { return mbThreadPersistence.countByG_C_S( groupId, categoryId, status); } } @Override public boolean hasAnswerMessage(long threadId) { int count = mbMessagePersistence.countByT_A(threadId, true); if (count > 0) { return true; } else { return false; } } @BufferedIncrement( configuration = "MBThread", incrementClass = NumberIncrement.class ) @Override public void incrementViewCounter(long threadId, int increment) throws PortalException { if (ExportImportThreadLocal.isImportInProcess()) { return; } MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId); thread.setModifiedDate(thread.getModifiedDate()); thread.setViewCount(thread.getViewCount() + increment); mbThreadPersistence.update(thread); } @Override public void moveDependentsToTrash( long groupId, long threadId, long trashEntryId) throws PortalException { Set<Long> userIds = new HashSet<>(); MBThread thread = mbThreadLocalService.getThread(threadId); List<MBMessage> messages = mbMessageLocalService.getThreadMessages( threadId, WorkflowConstants.STATUS_ANY); for (MBMessage message : messages) { // Message if (message.isDiscussion()) { continue; } int oldStatus = message.getStatus(); message.setStatus(WorkflowConstants.STATUS_IN_TRASH); mbMessagePersistence.update(message); userIds.add(message.getUserId()); // Trash int status = oldStatus; if (oldStatus == WorkflowConstants.STATUS_PENDING) { status = WorkflowConstants.STATUS_DRAFT; } if (oldStatus != WorkflowConstants.STATUS_APPROVED) { trashVersionLocalService.addTrashVersion( trashEntryId, MBMessage.class.getName(), message.getMessageId(), status, null); } // Asset if (oldStatus == WorkflowConstants.STATUS_APPROVED) { assetEntryLocalService.updateVisible( MBMessage.class.getName(), message.getMessageId(), false); } // Attachments for (FileEntry fileEntry : message.getAttachmentsFileEntries()) { PortletFileRepositoryUtil.movePortletFileEntryToTrash( thread.getStatusByUserId(), fileEntry.getFileEntryId()); } // Indexer Indexer<MBMessage> indexer = IndexerRegistryUtil.nullSafeGetIndexer( MBMessage.class); indexer.reindex(message); // Workflow if (oldStatus == WorkflowConstants.STATUS_PENDING) { workflowInstanceLinkLocalService.deleteWorkflowInstanceLink( message.getCompanyId(), message.getGroupId(), MBMessage.class.getName(), message.getMessageId()); } } // Statistics for (long userId : userIds) { mbStatsUserLocalService.updateStatsUser(groupId, userId); } } @Override public MBThread moveThread(long groupId, long categoryId, long threadId) throws PortalException { MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId); long oldCategoryId = thread.getCategoryId(); MBCategory oldCategory = null; if (oldCategoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) { oldCategory = mbCategoryPersistence.fetchByPrimaryKey( oldCategoryId); } MBCategory category = null; if (categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) { category = mbCategoryPersistence.fetchByPrimaryKey(categoryId); } // Thread thread.setCategoryId(categoryId); mbThreadPersistence.update(thread); // Messages List<MBMessage> messages = mbMessagePersistence.findByG_C_T( groupId, oldCategoryId, thread.getThreadId()); for (MBMessage message : messages) { message.setCategoryId(categoryId); mbMessagePersistence.update(message); // Indexer if (!message.isDiscussion()) { Indexer<MBMessage> indexer = IndexerRegistryUtil.nullSafeGetIndexer(MBMessage.class); indexer.reindex(message); } } // Category if ((oldCategory != null) && (categoryId != oldCategoryId)) { MBUtil.updateCategoryStatistics(oldCategory.getCategoryId()); } if ((category != null) && (categoryId != oldCategoryId)) { MBUtil.updateCategoryStatistics(category.getCategoryId()); } // Indexer Indexer<MBThread> indexer = IndexerRegistryUtil.nullSafeGetIndexer( MBThread.class); indexer.reindex(thread); return thread; } @Override public MBThread moveThreadFromTrash( long userId, long categoryId, long threadId) throws PortalException { MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId); if (!thread.isInTrash()) { throw new RestoreEntryException( RestoreEntryException.INVALID_STATUS); } if (thread.isInTrashExplicitly()) { restoreThreadFromTrash(userId, threadId); } else { // Thread TrashVersion trashVersion = trashVersionLocalService.fetchVersion( MBThread.class.getName(), thread.getThreadId()); int status = WorkflowConstants.STATUS_APPROVED; if (trashVersion != null) { status = trashVersion.getStatus(); } updateStatus(userId, threadId, status); // Trash if (trashVersion != null) { trashVersionLocalService.deleteTrashVersion(trashVersion); } // Messages restoreDependentsFromTrash(thread.getGroupId(), threadId); } return moveThread(thread.getGroupId(), categoryId, threadId); } @Override public void moveThreadsToTrash(long groupId, long userId) throws PortalException { List<MBThread> threads = mbThreadPersistence.findByGroupId(groupId); for (MBThread thread : threads) { moveThreadToTrash(userId, thread); } } @Override public MBThread moveThreadToTrash(long userId, long threadId) throws PortalException { MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId); return moveThreadToTrash(userId, thread); } @Override public MBThread moveThreadToTrash(long userId, MBThread thread) throws PortalException { // Thread if (thread.isInTrash()) { throw new TrashEntryException(); } if (thread.getCategoryId() == MBCategoryConstants.DISCUSSION_CATEGORY_ID) { return thread; } int oldStatus = thread.getStatus(); if (oldStatus == WorkflowConstants.STATUS_PENDING) { thread.setStatus(WorkflowConstants.STATUS_DRAFT); mbThreadPersistence.update(thread); } thread = updateStatus( userId, thread.getThreadId(), WorkflowConstants.STATUS_IN_TRASH); // Trash TrashEntry trashEntry = trashEntryLocalService.addTrashEntry( userId, thread.getGroupId(), MBThread.class.getName(), thread.getThreadId(), thread.getUuid(), null, oldStatus, null, null); // Messages moveDependentsToTrash( thread.getGroupId(), thread.getThreadId(), trashEntry.getEntryId()); // Social MBMessage message = mbMessageLocalService.getMBMessage( thread.getRootMessageId()); JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject(); extraDataJSONObject.put("rootMessageId", thread.getRootMessageId()); extraDataJSONObject.put("title", message.getSubject()); SocialActivityManagerUtil.addActivity( userId, thread, SocialActivityConstants.TYPE_MOVE_TO_TRASH, extraDataJSONObject.toString(), 0); return thread; } @Override public void restoreDependentsFromTrash(long groupId, long threadId) throws PortalException { Set<Long> userIds = new HashSet<>(); MBThread thread = mbThreadLocalService.getThread(threadId); List<MBMessage> messages = mbMessageLocalService.getThreadMessages( threadId, WorkflowConstants.STATUS_ANY); for (MBMessage message : messages) { // Message if (message.isDiscussion()) { continue; } TrashVersion trashVersion = trashVersionLocalService.fetchVersion( MBMessage.class.getName(), message.getMessageId()); int oldStatus = WorkflowConstants.STATUS_APPROVED; if (trashVersion != null) { oldStatus = trashVersion.getStatus(); } message.setStatus(oldStatus); mbMessagePersistence.update(message); userIds.add(message.getUserId()); // Trash if (trashVersion != null) { trashVersionLocalService.deleteTrashVersion(trashVersion); } // Asset if (oldStatus == WorkflowConstants.STATUS_APPROVED) { assetEntryLocalService.updateVisible( MBMessage.class.getName(), message.getMessageId(), true); } // Attachments for (FileEntry fileEntry : message.getDeletedAttachmentsFileEntries()) { PortletFileRepositoryUtil.restorePortletFileEntryFromTrash( thread.getStatusByUserId(), fileEntry.getFileEntryId()); } // Indexer Indexer<MBMessage> indexer = IndexerRegistryUtil.nullSafeGetIndexer( MBMessage.class); indexer.reindex(message); } // Statistics for (long userId : userIds) { mbStatsUserLocalService.updateStatsUser(groupId, userId); } } /** * @deprecated As of 7.0.0, replaced by {@link * #restoreDependentsFromTrash(long, long)} */ @Deprecated @Override public void restoreDependentsFromTrash( long groupId, long threadId, long trashEntryId) throws PortalException { restoreDependentsFromTrash(groupId, threadId); } @Override public void restoreThreadFromTrash(long userId, long threadId) throws PortalException { // Thread MBThread thread = getThread(threadId); if (!thread.isInTrash()) { throw new RestoreEntryException( RestoreEntryException.INVALID_STATUS); } if (thread.getCategoryId() == MBCategoryConstants.DISCUSSION_CATEGORY_ID) { return; } TrashEntry trashEntry = trashEntryLocalService.getEntry( MBThread.class.getName(), threadId); updateStatus(userId, threadId, trashEntry.getStatus()); // Messages restoreDependentsFromTrash(thread.getGroupId(), threadId); // Trash trashEntryLocalService.deleteEntry(trashEntry.getEntryId()); // Social MBMessage message = mbMessageLocalService.getMBMessage( thread.getRootMessageId()); JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject(); extraDataJSONObject.put("rootMessageId", thread.getRootMessageId()); extraDataJSONObject.put("title", message.getSubject()); SocialActivityManagerUtil.addActivity( userId, thread, SocialActivityConstants.TYPE_RESTORE_FROM_TRASH, extraDataJSONObject.toString(), 0); } @Override public Hits search( long groupId, long userId, long creatorUserId, int status, int start, int end) throws PortalException { return search(groupId, userId, creatorUserId, 0, 0, status, start, end); } @Override public Hits search( long groupId, long userId, long creatorUserId, long startDate, long endDate, int status, int start, int end) throws PortalException { Indexer<MBThread> indexer = IndexerRegistryUtil.getIndexer( MBThread.class.getName()); SearchContext searchContext = new SearchContext(); searchContext.setAttribute(Field.STATUS, status); if (endDate > 0) { searchContext.setAttribute("endDate", endDate); } searchContext.setAttribute("paginationType", "none"); if (creatorUserId > 0) { searchContext.setAttribute( "participantUserId", String.valueOf(creatorUserId)); } if (startDate > 0) { searchContext.setAttribute("startDate", startDate); } Group group = groupLocalService.getGroup(groupId); searchContext.setCompanyId(group.getCompanyId()); searchContext.setEnd(end); searchContext.setGroupIds(new long[] {groupId}); searchContext.setSorts(new Sort("lastPostDate", true)); searchContext.setStart(start); searchContext.setUserId(userId); return indexer.search(searchContext); } @Override public MBThread splitThread( long userId, long messageId, String subject, ServiceContext serviceContext) throws PortalException { MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId); if (message.isRoot()) { throw new SplitThreadException( "Unable to split message " + messageId + " because it is a root message"); } MBCategory category = message.getCategory(); MBThread oldThread = message.getThread(); MBMessage rootMessage = mbMessagePersistence.findByPrimaryKey( oldThread.getRootMessageId()); long oldAttachmentsFolderId = message.getAttachmentsFolderId(); // Message flags mbMessageLocalService.updateAnswer(message, false, true); // Create new thread MBThread thread = addThread( message.getCategoryId(), message, serviceContext); mbThreadPersistence.update(oldThread); // Update messages if (Validator.isNotNull(subject)) { MBMessageDisplay messageDisplay = mbMessageLocalService.getMessageDisplay( userId, messageId, WorkflowConstants.STATUS_ANY); MBTreeWalker treeWalker = messageDisplay.getTreeWalker(); List<MBMessage> messages = treeWalker.getMessages(); int[] range = treeWalker.getChildrenRange(message); for (int i = range[0]; i < range[1]; i++) { MBMessage curMessage = messages.get(i); String oldSubject = message.getSubject(); String curSubject = curMessage.getSubject(); if (oldSubject.startsWith( MBMessageConstants.MESSAGE_SUBJECT_PREFIX_RE)) { curSubject = StringUtil.replace( curSubject, rootMessage.getSubject(), subject); } else { curSubject = StringUtil.replace( curSubject, oldSubject, subject); } curMessage.setSubject(curSubject); mbMessagePersistence.update(curMessage); } message.setSubject(subject); } message.setThreadId(thread.getThreadId()); message.setRootMessageId(thread.getRootMessageId()); message.setParentMessageId(0); mbMessagePersistence.update(message); // Attachments moveAttachmentsFolders( message, oldAttachmentsFolderId, oldThread, thread, serviceContext); // Indexer if (!message.isDiscussion()) { Indexer<MBMessage> indexer = IndexerRegistryUtil.nullSafeGetIndexer( MBMessage.class); indexer.reindex(message); } // Update children moveChildrenMessages(message, category, oldThread.getThreadId()); // Update new thread MBUtil.updateThreadMessageCount(thread.getThreadId()); // Update old thread MBUtil.updateThreadMessageCount(oldThread.getThreadId()); // Category if ((message.getCategoryId() != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) && (message.getCategoryId() != MBCategoryConstants.DISCUSSION_CATEGORY_ID)) { MBUtil.updateCategoryThreadCount(category.getCategoryId()); } // Indexer Indexer<MBThread> indexer = IndexerRegistryUtil.nullSafeGetIndexer( MBThread.class); indexer.reindex(oldThread); indexer.reindex(message.getThread()); return thread; } @Override public MBThread updateMessageCount(long threadId) { MBThread mbThread = mbThreadPersistence.fetchByPrimaryKey(threadId); if (mbThread == null) { return null; } int messageCount = mbMessageLocalService.getThreadMessagesCount( threadId, WorkflowConstants.STATUS_APPROVED); mbThread.setMessageCount(messageCount); return mbThreadPersistence.update(mbThread); } @Override public void updateQuestion(long threadId, boolean question) throws PortalException { MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId); if (thread.isQuestion() == question) { return; } thread.setQuestion(question); mbThreadPersistence.update(thread); if (!question) { MBMessage message = mbMessagePersistence.findByPrimaryKey( thread.getRootMessageId()); mbMessageLocalService.updateAnswer(message, false, true); } } @Override public MBThread updateStatus(long userId, long threadId, int status) throws PortalException { MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId); // Thread User user = userPersistence.findByPrimaryKey(userId); thread.setStatus(status); thread.setStatusByUserId(user.getUserId()); thread.setStatusByUserName(user.getFullName()); thread.setStatusDate(new Date()); mbThreadPersistence.update(thread); // Messages if (thread.getCategoryId() != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) { // Category MBCategory category = mbCategoryPersistence.fetchByPrimaryKey( thread.getCategoryId()); if (category != null) { MBUtil.updateCategoryStatistics(category.getCategoryId()); } } // Indexer Indexer<MBThread> indexer = IndexerRegistryUtil.nullSafeGetIndexer( MBThread.class); indexer.reindex(thread); return thread; } protected void moveAttachmentsFolders( MBMessage message, long oldAttachmentsFolderId, MBThread oldThread, MBThread newThread, ServiceContext serviceContext) throws PortalException { if (oldAttachmentsFolderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) { Folder newThreadFolder = newThread.addAttachmentsFolder(); PortletFileRepositoryUtil.movePortletFolder( message.getGroupId(), message.getUserId(), oldAttachmentsFolderId, newThreadFolder.getFolderId(), serviceContext); } List<MBMessage> childMessages = mbMessagePersistence.findByT_P( oldThread.getThreadId(), message.getMessageId()); for (MBMessage childMessage : childMessages) { moveAttachmentsFolders( childMessage, childMessage.getAttachmentsFolderId(), oldThread, newThread, serviceContext); } } protected void moveChildrenMessages( MBMessage parentMessage, MBCategory category, long oldThreadId) throws PortalException { List<MBMessage> messages = mbMessagePersistence.findByT_P( oldThreadId, parentMessage.getMessageId()); for (MBMessage message : messages) { message.setCategoryId(parentMessage.getCategoryId()); message.setThreadId(parentMessage.getThreadId()); message.setRootMessageId(parentMessage.getRootMessageId()); mbMessagePersistence.update(message); if (!message.isDiscussion()) { Indexer<MBMessage> indexer = IndexerRegistryUtil.nullSafeGetIndexer(MBMessage.class); indexer.reindex(message); } moveChildrenMessages(message, category, oldThreadId); } } }