001
014
015 package com.liferay.portlet.messageboards.service.impl;
016
017 import com.liferay.portal.kernel.dao.orm.QueryDefinition;
018 import com.liferay.portal.kernel.exception.PortalException;
019 import com.liferay.portal.kernel.increment.BufferedIncrement;
020 import com.liferay.portal.kernel.increment.NumberIncrement;
021 import com.liferay.portal.kernel.json.JSONFactoryUtil;
022 import com.liferay.portal.kernel.json.JSONObject;
023 import com.liferay.portal.kernel.repository.model.FileEntry;
024 import com.liferay.portal.kernel.repository.model.Folder;
025 import com.liferay.portal.kernel.search.Field;
026 import com.liferay.portal.kernel.search.Hits;
027 import com.liferay.portal.kernel.search.Indexer;
028 import com.liferay.portal.kernel.search.IndexerRegistryUtil;
029 import com.liferay.portal.kernel.search.SearchContext;
030 import com.liferay.portal.kernel.search.Sort;
031 import com.liferay.portal.kernel.social.SocialActivityManagerUtil;
032 import com.liferay.portal.kernel.systemevent.SystemEvent;
033 import com.liferay.portal.kernel.util.StringUtil;
034 import com.liferay.portal.kernel.util.Validator;
035 import com.liferay.portal.kernel.workflow.WorkflowConstants;
036 import com.liferay.portal.model.Group;
037 import com.liferay.portal.model.ResourceConstants;
038 import com.liferay.portal.model.SystemEventConstants;
039 import com.liferay.portal.model.User;
040 import com.liferay.portal.portletfilerepository.PortletFileRepositoryUtil;
041 import com.liferay.portal.service.ServiceContext;
042 import com.liferay.portlet.asset.model.AssetEntry;
043 import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
044 import com.liferay.portlet.exportimport.lar.ExportImportThreadLocal;
045 import com.liferay.portlet.messageboards.constants.MBConstants;
046 import com.liferay.portlet.messageboards.exception.NoSuchCategoryException;
047 import com.liferay.portlet.messageboards.exception.SplitThreadException;
048 import com.liferay.portlet.messageboards.model.MBCategory;
049 import com.liferay.portlet.messageboards.model.MBCategoryConstants;
050 import com.liferay.portlet.messageboards.model.MBMessage;
051 import com.liferay.portlet.messageboards.model.MBMessageDisplay;
052 import com.liferay.portlet.messageboards.model.MBThread;
053 import com.liferay.portlet.messageboards.model.MBThreadConstants;
054 import com.liferay.portlet.messageboards.model.MBTreeWalker;
055 import com.liferay.portlet.messageboards.service.base.MBThreadLocalServiceBaseImpl;
056 import com.liferay.portlet.messageboards.util.MBUtil;
057 import com.liferay.portlet.social.model.SocialActivityConstants;
058 import com.liferay.portlet.trash.model.TrashEntry;
059 import com.liferay.portlet.trash.model.TrashVersion;
060
061 import java.util.ArrayList;
062 import java.util.Date;
063 import java.util.HashSet;
064 import java.util.List;
065 import java.util.Set;
066
067
071 public class MBThreadLocalServiceImpl extends MBThreadLocalServiceBaseImpl {
072
073 @Override
074 public MBThread addThread(
075 long categoryId, MBMessage message, ServiceContext serviceContext)
076 throws PortalException {
077
078
079
080 long threadId = message.getThreadId();
081
082 if (!message.isRoot() || (threadId <= 0)) {
083 threadId = counterLocalService.increment();
084 }
085
086 MBThread thread = mbThreadPersistence.create(threadId);
087
088 thread.setUuid(serviceContext.getUuid());
089 thread.setGroupId(message.getGroupId());
090 thread.setCompanyId(message.getCompanyId());
091 thread.setUserId(message.getUserId());
092 thread.setUserName(message.getUserName());
093 thread.setCategoryId(categoryId);
094 thread.setRootMessageId(message.getMessageId());
095 thread.setRootMessageUserId(message.getUserId());
096
097 if (message.isAnonymous()) {
098 thread.setLastPostByUserId(0);
099 }
100 else {
101 thread.setLastPostByUserId(message.getUserId());
102 }
103
104 thread.setLastPostDate(message.getModifiedDate());
105
106 if (message.getPriority() != MBThreadConstants.PRIORITY_NOT_GIVEN) {
107 thread.setPriority(message.getPriority());
108 }
109
110 thread.setStatus(message.getStatus());
111 thread.setStatusByUserId(message.getStatusByUserId());
112 thread.setStatusByUserName(message.getStatusByUserName());
113 thread.setStatusDate(message.getStatusDate());
114
115 mbThreadPersistence.update(thread);
116
117
118
119 if (categoryId >= 0) {
120 assetEntryLocalService.updateEntry(
121 message.getUserId(), message.getGroupId(),
122 thread.getStatusDate(), thread.getLastPostDate(),
123 MBThread.class.getName(), thread.getThreadId(),
124 thread.getUuid(), 0, new long[0], new String[0], false, null,
125 null, null, null, String.valueOf(thread.getRootMessageId()),
126 null, null, null, null, 0, 0,
127 serviceContext.getAssetPriority());
128 }
129
130 return thread;
131 }
132
133 @Override
134 public void deleteThread(long threadId) throws PortalException {
135 MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
136
137 mbThreadLocalService.deleteThread(thread);
138 }
139
140 @Override
141 @SystemEvent(
142 action = SystemEventConstants.ACTION_SKIP,
143 type = SystemEventConstants.TYPE_DELETE
144 )
145 public void deleteThread(MBThread thread) throws PortalException {
146 MBMessage rootMessage = mbMessagePersistence.findByPrimaryKey(
147 thread.getRootMessageId());
148
149
150
151 Indexer<MBMessage> messageIndexer =
152 IndexerRegistryUtil.nullSafeGetIndexer(MBMessage.class);
153
154
155
156 long folderId = thread.getAttachmentsFolderId();
157
158 if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
159 PortletFileRepositoryUtil.deletePortletFolder(folderId);
160 }
161
162
163
164 subscriptionLocalService.deleteSubscriptions(
165 thread.getCompanyId(), MBThread.class.getName(),
166 thread.getThreadId());
167
168
169
170 mbThreadFlagLocalService.deleteThreadFlagsByThreadId(
171 thread.getThreadId());
172
173
174
175 List<MBMessage> messages = mbMessagePersistence.findByThreadId(
176 thread.getThreadId());
177
178 for (MBMessage message : messages) {
179
180
181
182 ratingsStatsLocalService.deleteStats(
183 message.getWorkflowClassName(), message.getMessageId());
184
185
186
187 assetEntryLocalService.deleteEntry(
188 message.getWorkflowClassName(), message.getMessageId());
189
190
191
192 if (!message.isDiscussion()) {
193 resourceLocalService.deleteResource(
194 message.getCompanyId(), message.getWorkflowClassName(),
195 ResourceConstants.SCOPE_INDIVIDUAL, message.getMessageId());
196 }
197
198
199
200 mbMessagePersistence.remove(message);
201
202
203
204 messageIndexer.delete(message);
205
206
207
208 if (!message.isDiscussion()) {
209 mbStatsUserLocalService.updateStatsUser(
210 message.getGroupId(), message.getUserId());
211 }
212
213
214
215 workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
216 message.getCompanyId(), message.getGroupId(),
217 message.getWorkflowClassName(), message.getMessageId());
218 }
219
220
221
222 if ((rootMessage.getCategoryId() !=
223 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
224 (rootMessage.getCategoryId() !=
225 MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
226
227 try {
228 MBCategory category = mbCategoryPersistence.findByPrimaryKey(
229 thread.getCategoryId());
230
231 MBUtil.updateCategoryStatistics(category.getCategoryId());
232 }
233 catch (NoSuchCategoryException nsce) {
234 if (!thread.isInTrash()) {
235 throw nsce;
236 }
237 }
238 }
239
240
241
242 AssetEntry assetEntry = assetEntryLocalService.fetchEntry(
243 MBThread.class.getName(), thread.getThreadId());
244
245 if (assetEntry != null) {
246 assetEntry.setTitle(rootMessage.getSubject());
247
248 assetEntryLocalService.updateAssetEntry(assetEntry);
249 }
250
251 assetEntryLocalService.deleteEntry(
252 MBThread.class.getName(), thread.getThreadId());
253
254
255
256 if (thread.isInTrashExplicitly()) {
257 trashEntryLocalService.deleteEntry(
258 MBThread.class.getName(), thread.getThreadId());
259 }
260 else {
261 trashVersionLocalService.deleteTrashVersion(
262 MBThread.class.getName(), thread.getThreadId());
263 }
264
265
266
267 Indexer<MBThread> threadIndexer =
268 IndexerRegistryUtil.nullSafeGetIndexer(MBThread.class);
269
270 threadIndexer.delete(thread);
271
272
273
274 mbThreadPersistence.remove(thread);
275 }
276
277 @Override
278 public void deleteThreads(long groupId, long categoryId)
279 throws PortalException {
280
281 deleteThreads(groupId, categoryId, true);
282 }
283
284 @Override
285 public void deleteThreads(
286 long groupId, long categoryId, boolean includeTrashedEntries)
287 throws PortalException {
288
289 List<MBThread> threads = mbThreadPersistence.findByG_C(
290 groupId, categoryId);
291
292 for (MBThread thread : threads) {
293 if (includeTrashedEntries || !thread.isInTrashExplicitly()) {
294 mbThreadLocalService.deleteThread(thread);
295 }
296 }
297
298 if (mbThreadPersistence.countByGroupId(groupId) == 0) {
299 PortletFileRepositoryUtil.deletePortletRepository(
300 groupId, MBConstants.SERVICE_NAME);
301 }
302 }
303
304 @Override
305 public MBThread fetchThread(long threadId) {
306 return mbThreadPersistence.fetchByPrimaryKey(threadId);
307 }
308
309 @Override
310 public int getCategoryThreadsCount(
311 long groupId, long categoryId, int status) {
312
313 if (status == WorkflowConstants.STATUS_ANY) {
314 return mbThreadPersistence.countByG_C(groupId, categoryId);
315 }
316 else {
317 return mbThreadPersistence.countByG_C_S(
318 groupId, categoryId, status);
319 }
320 }
321
322
326 @Deprecated
327 @Override
328 public List<MBThread> getGroupThreads(
329 long groupId, int status, int start, int end) {
330
331 QueryDefinition<MBThread> queryDefinition = new QueryDefinition<>(
332 status, start, end, null);
333
334 return getGroupThreads(groupId, queryDefinition);
335 }
336
337 @Override
338 public List<MBThread> getGroupThreads(
339 long groupId, long userId, boolean subscribed, boolean includeAnonymous,
340 QueryDefinition<MBThread> queryDefinition) {
341
342 if (userId <= 0) {
343 return getGroupThreads(groupId, queryDefinition);
344 }
345
346 if (subscribed) {
347 return mbThreadFinder.findByS_G_U_C(
348 groupId, userId, null, queryDefinition);
349 }
350 else {
351 if (includeAnonymous) {
352 return mbThreadFinder.findByG_U_C(
353 groupId, userId, null, queryDefinition);
354 }
355 else {
356 return mbThreadFinder.findByG_U_C_A(
357 groupId, userId, null, false, queryDefinition);
358 }
359 }
360 }
361
362 @Override
363 public List<MBThread> getGroupThreads(
364 long groupId, long userId, boolean subscribed,
365 QueryDefinition<MBThread> queryDefinition) {
366
367 return getGroupThreads(
368 groupId, userId, subscribed, true, queryDefinition);
369 }
370
371
375 @Deprecated
376 @Override
377 public List<MBThread> getGroupThreads(
378 long groupId, long userId, int status, boolean subscribed,
379 boolean includeAnonymous, int start, int end) {
380
381 QueryDefinition<MBThread> queryDefinition = new QueryDefinition<>(
382 status, start, end, null);
383
384 return getGroupThreads(
385 groupId, userId, subscribed, includeAnonymous, queryDefinition);
386 }
387
388
392 @Deprecated
393 @Override
394 public List<MBThread> getGroupThreads(
395 long groupId, long userId, int status, boolean subscribed, int start,
396 int end) {
397
398 QueryDefinition<MBThread> queryDefinition = new QueryDefinition<>(
399 status, start, end, null);
400
401 return getGroupThreads(groupId, userId, subscribed, queryDefinition);
402 }
403
404
408 @Deprecated
409 @Override
410 public List<MBThread> getGroupThreads(
411 long groupId, long userId, int status, int start, int end) {
412
413 QueryDefinition<MBThread> queryDefinition = new QueryDefinition<>(
414 status, start, end, null);
415
416 return getGroupThreads(groupId, userId, false, queryDefinition);
417 }
418
419 @Override
420 public List<MBThread> getGroupThreads(
421 long groupId, long userId, QueryDefinition<MBThread> queryDefinition) {
422
423 return getGroupThreads(groupId, userId, false, queryDefinition);
424 }
425
426 @Override
427 public List<MBThread> getGroupThreads(
428 long groupId, QueryDefinition<MBThread> queryDefinition) {
429
430 if (queryDefinition.isExcludeStatus()) {
431 return mbThreadPersistence.findByG_NotC_NotS(
432 groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID,
433 queryDefinition.getStatus(), queryDefinition.getStart(),
434 queryDefinition.getEnd());
435 }
436 else {
437 return mbThreadPersistence.findByG_NotC_S(
438 groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID,
439 queryDefinition.getStatus(), queryDefinition.getStart(),
440 queryDefinition.getEnd());
441 }
442 }
443
444
448 @Deprecated
449 @Override
450 public int getGroupThreadsCount(long groupId, int status) {
451 QueryDefinition<MBThread> queryDefinition = new QueryDefinition<>(
452 status);
453
454 return getGroupThreadsCount(groupId, queryDefinition);
455 }
456
457 @Override
458 public int getGroupThreadsCount(
459 long groupId, long userId, boolean subscribed, boolean includeAnonymous,
460 QueryDefinition<MBThread> queryDefinition) {
461
462 if (userId <= 0) {
463 return getGroupThreadsCount(groupId, queryDefinition);
464 }
465
466 if (subscribed) {
467 return mbThreadFinder.countByS_G_U_C(
468 groupId, userId, null, queryDefinition);
469 }
470 else {
471 if (includeAnonymous) {
472 return mbThreadFinder.countByG_U_C(
473 groupId, userId, null, queryDefinition);
474 }
475 else {
476 return mbThreadFinder.countByG_U_C_A(
477 groupId, userId, null, false, queryDefinition);
478 }
479 }
480 }
481
482 @Override
483 public int getGroupThreadsCount(
484 long groupId, long userId, boolean subscribed,
485 QueryDefinition<MBThread> queryDefinition) {
486
487 return getGroupThreadsCount(
488 groupId, userId, subscribed, true, queryDefinition);
489 }
490
491
495 @Deprecated
496 @Override
497 public int getGroupThreadsCount(long groupId, long userId, int status) {
498 QueryDefinition<MBThread> queryDefinition = new QueryDefinition<>(
499 status);
500
501 return getGroupThreadsCount(groupId, userId, false, queryDefinition);
502 }
503
504
508 @Deprecated
509 @Override
510 public int getGroupThreadsCount(
511 long groupId, long userId, int status, boolean subscribed) {
512
513 QueryDefinition<MBThread> queryDefinition = new QueryDefinition<>(
514 status);
515
516 return getGroupThreadsCount(
517 groupId, userId, subscribed, true, queryDefinition);
518 }
519
520
524 @Deprecated
525 @Override
526 public int getGroupThreadsCount(
527 long groupId, long userId, int status, boolean subscribed,
528 boolean includeAnonymous) {
529
530 QueryDefinition<MBThread> queryDefinition = new QueryDefinition<>(
531 status);
532
533 return getGroupThreadsCount(
534 groupId, userId, subscribed, includeAnonymous, queryDefinition);
535 }
536
537 @Override
538 public int getGroupThreadsCount(
539 long groupId, long userId, QueryDefinition<MBThread> queryDefinition) {
540
541 return getGroupThreadsCount(groupId, userId, false, queryDefinition);
542 }
543
544 @Override
545 public int getGroupThreadsCount(
546 long groupId, QueryDefinition<MBThread> queryDefinition) {
547
548 if (queryDefinition.isExcludeStatus()) {
549 return mbThreadPersistence.countByG_NotC_NotS(
550 groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID,
551 queryDefinition.getStatus());
552 }
553 else {
554 return mbThreadPersistence.countByG_NotC_S(
555 groupId, MBCategoryConstants.DISCUSSION_CATEGORY_ID,
556 queryDefinition.getStatus());
557 }
558 }
559
560 @Override
561 public List<MBThread> getNoAssetThreads() {
562 return mbThreadFinder.findByNoAssets();
563 }
564
565 @Override
566 public List<MBThread> getPriorityThreads(long categoryId, double priority)
567 throws PortalException {
568
569 return getPriorityThreads(categoryId, priority, false);
570 }
571
572 @Override
573 public List<MBThread> getPriorityThreads(
574 long categoryId, double priority, boolean inherit)
575 throws PortalException {
576
577 if (!inherit) {
578 return mbThreadPersistence.findByC_P(categoryId, priority);
579 }
580
581 List<MBThread> threads = new ArrayList<>();
582
583 while ((categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
584 (categoryId != MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
585
586 threads.addAll(
587 0, mbThreadPersistence.findByC_P(categoryId, priority));
588
589 MBCategory category = mbCategoryPersistence.findByPrimaryKey(
590 categoryId);
591
592 categoryId = category.getParentCategoryId();
593 }
594
595 return threads;
596 }
597
598 @Override
599 public MBThread getThread(long threadId) throws PortalException {
600 return mbThreadPersistence.findByPrimaryKey(threadId);
601 }
602
603 @Override
604 public List<MBThread> getThreads(
605 long groupId, long categoryId, int status, int start, int end) {
606
607 if (status == WorkflowConstants.STATUS_ANY) {
608 return mbThreadPersistence.findByG_C(
609 groupId, categoryId, start, end);
610 }
611 else {
612 return mbThreadPersistence.findByG_C_S(
613 groupId, categoryId, status, start, end);
614 }
615 }
616
617 @Override
618 public int getThreadsCount(long groupId, long categoryId, int status) {
619 if (status == WorkflowConstants.STATUS_ANY) {
620 return mbThreadPersistence.countByG_C(groupId, categoryId);
621 }
622 else {
623 return mbThreadPersistence.countByG_C_S(
624 groupId, categoryId, status);
625 }
626 }
627
628 @Override
629 public boolean hasAnswerMessage(long threadId) {
630 int count = mbMessagePersistence.countByT_A(threadId, true);
631
632 if (count > 0) {
633 return true;
634 }
635 else {
636 return false;
637 }
638 }
639
640 @BufferedIncrement(
641 configuration = "MBThread", incrementClass = NumberIncrement.class
642 )
643 @Override
644 public void incrementViewCounter(long threadId, int increment)
645 throws PortalException {
646
647 if (ExportImportThreadLocal.isImportInProcess()) {
648 return;
649 }
650
651 MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
652
653 thread.setModifiedDate(thread.getModifiedDate());
654 thread.setViewCount(thread.getViewCount() + increment);
655
656 mbThreadPersistence.update(thread);
657 }
658
659 @Override
660 public void moveDependentsToTrash(
661 long groupId, long threadId, long trashEntryId)
662 throws PortalException {
663
664 Set<Long> userIds = new HashSet<>();
665
666 MBThread thread = mbThreadLocalService.getThread(threadId);
667
668 List<MBMessage> messages = mbMessageLocalService.getThreadMessages(
669 threadId, WorkflowConstants.STATUS_ANY);
670
671 for (MBMessage message : messages) {
672
673
674
675 if (message.isDiscussion()) {
676 continue;
677 }
678
679 int oldStatus = message.getStatus();
680
681 message.setStatus(WorkflowConstants.STATUS_IN_TRASH);
682
683 mbMessagePersistence.update(message);
684
685 userIds.add(message.getUserId());
686
687
688
689 int status = oldStatus;
690
691 if (oldStatus == WorkflowConstants.STATUS_PENDING) {
692 status = WorkflowConstants.STATUS_DRAFT;
693 }
694
695 if (oldStatus != WorkflowConstants.STATUS_APPROVED) {
696 trashVersionLocalService.addTrashVersion(
697 trashEntryId, MBMessage.class.getName(),
698 message.getMessageId(), status, null);
699 }
700
701
702
703 if (oldStatus == WorkflowConstants.STATUS_APPROVED) {
704 assetEntryLocalService.updateVisible(
705 MBMessage.class.getName(), message.getMessageId(), false);
706 }
707
708
709
710 for (FileEntry fileEntry : message.getAttachmentsFileEntries()) {
711 PortletFileRepositoryUtil.movePortletFileEntryToTrash(
712 thread.getStatusByUserId(), fileEntry.getFileEntryId());
713 }
714
715
716
717 Indexer<MBMessage> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
718 MBMessage.class);
719
720 indexer.reindex(message);
721
722
723
724 if (oldStatus == WorkflowConstants.STATUS_PENDING) {
725 workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
726 message.getCompanyId(), message.getGroupId(),
727 MBMessage.class.getName(), message.getMessageId());
728 }
729 }
730
731
732
733 for (long userId : userIds) {
734 mbStatsUserLocalService.updateStatsUser(groupId, userId);
735 }
736 }
737
738 @Override
739 public MBThread moveThread(long groupId, long categoryId, long threadId)
740 throws PortalException {
741
742 MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
743
744 long oldCategoryId = thread.getCategoryId();
745
746 MBCategory oldCategory = null;
747
748 if (oldCategoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
749 oldCategory = mbCategoryPersistence.fetchByPrimaryKey(
750 oldCategoryId);
751 }
752
753 MBCategory category = null;
754
755 if (categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
756 category = mbCategoryPersistence.fetchByPrimaryKey(categoryId);
757 }
758
759
760
761 thread.setCategoryId(categoryId);
762
763 mbThreadPersistence.update(thread);
764
765
766
767 List<MBMessage> messages = mbMessagePersistence.findByG_C_T(
768 groupId, oldCategoryId, thread.getThreadId());
769
770 for (MBMessage message : messages) {
771 message.setCategoryId(categoryId);
772
773 mbMessagePersistence.update(message);
774
775
776
777 if (!message.isDiscussion()) {
778 Indexer<MBMessage> indexer =
779 IndexerRegistryUtil.nullSafeGetIndexer(MBMessage.class);
780
781 indexer.reindex(message);
782 }
783 }
784
785
786
787 if ((oldCategory != null) && (categoryId != oldCategoryId)) {
788 MBUtil.updateCategoryStatistics(oldCategory.getCategoryId());
789 }
790
791 if ((category != null) && (categoryId != oldCategoryId)) {
792 MBUtil.updateCategoryStatistics(category.getCategoryId());
793 }
794
795
796
797 Indexer<MBThread> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
798 MBThread.class);
799
800 indexer.reindex(thread);
801
802 return thread;
803 }
804
805 @Override
806 public MBThread moveThreadFromTrash(
807 long userId, long categoryId, long threadId)
808 throws PortalException {
809
810 MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
811
812 if (thread.isInTrashExplicitly()) {
813 restoreThreadFromTrash(userId, threadId);
814 }
815 else {
816
817
818
819 TrashVersion trashVersion = trashVersionLocalService.fetchVersion(
820 MBThread.class.getName(), thread.getThreadId());
821
822 int status = WorkflowConstants.STATUS_APPROVED;
823
824 if (trashVersion != null) {
825 status = trashVersion.getStatus();
826 }
827
828 updateStatus(userId, threadId, status);
829
830
831
832 if (trashVersion != null) {
833 trashVersionLocalService.deleteTrashVersion(trashVersion);
834 }
835
836
837
838 restoreDependentsFromTrash(thread.getGroupId(), threadId);
839 }
840
841 return moveThread(thread.getGroupId(), categoryId, threadId);
842 }
843
844 @Override
845 public void moveThreadsToTrash(long groupId, long userId)
846 throws PortalException {
847
848 List<MBThread> threads = mbThreadPersistence.findByGroupId(groupId);
849
850 for (MBThread thread : threads) {
851 moveThreadToTrash(userId, thread);
852 }
853 }
854
855 @Override
856 public MBThread moveThreadToTrash(long userId, long threadId)
857 throws PortalException {
858
859 MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
860
861 return moveThreadToTrash(userId, thread);
862 }
863
864 @Override
865 public MBThread moveThreadToTrash(long userId, MBThread thread)
866 throws PortalException {
867
868
869
870 if (thread.getCategoryId() ==
871 MBCategoryConstants.DISCUSSION_CATEGORY_ID) {
872
873 return thread;
874 }
875
876 int oldStatus = thread.getStatus();
877
878 if (oldStatus == WorkflowConstants.STATUS_PENDING) {
879 thread.setStatus(WorkflowConstants.STATUS_DRAFT);
880
881 mbThreadPersistence.update(thread);
882 }
883
884 thread = updateStatus(
885 userId, thread.getThreadId(), WorkflowConstants.STATUS_IN_TRASH);
886
887
888
889 TrashEntry trashEntry = trashEntryLocalService.addTrashEntry(
890 userId, thread.getGroupId(), MBThread.class.getName(),
891 thread.getThreadId(), thread.getUuid(), null, oldStatus, null,
892 null);
893
894
895
896 moveDependentsToTrash(
897 thread.getGroupId(), thread.getThreadId(), trashEntry.getEntryId());
898
899
900
901 MBMessage message = mbMessageLocalService.getMBMessage(
902 thread.getRootMessageId());
903
904 JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
905
906 extraDataJSONObject.put("rootMessageId", thread.getRootMessageId());
907 extraDataJSONObject.put("title", message.getSubject());
908
909 SocialActivityManagerUtil.addActivity(
910 userId, thread, SocialActivityConstants.TYPE_MOVE_TO_TRASH,
911 extraDataJSONObject.toString(), 0);
912
913 return thread;
914 }
915
916 @Override
917 public void restoreDependentsFromTrash(long groupId, long threadId)
918 throws PortalException {
919
920 Set<Long> userIds = new HashSet<>();
921
922 MBThread thread = mbThreadLocalService.getThread(threadId);
923
924 List<MBMessage> messages = mbMessageLocalService.getThreadMessages(
925 threadId, WorkflowConstants.STATUS_ANY);
926
927 for (MBMessage message : messages) {
928
929
930
931 if (message.isDiscussion()) {
932 continue;
933 }
934
935 TrashVersion trashVersion = trashVersionLocalService.fetchVersion(
936 MBMessage.class.getName(), message.getMessageId());
937
938 int oldStatus = WorkflowConstants.STATUS_APPROVED;
939
940 if (trashVersion != null) {
941 oldStatus = trashVersion.getStatus();
942 }
943
944 message.setStatus(oldStatus);
945
946 mbMessagePersistence.update(message);
947
948 userIds.add(message.getUserId());
949
950
951
952 if (trashVersion != null) {
953 trashVersionLocalService.deleteTrashVersion(trashVersion);
954 }
955
956
957
958 if (oldStatus == WorkflowConstants.STATUS_APPROVED) {
959 assetEntryLocalService.updateVisible(
960 MBMessage.class.getName(), message.getMessageId(), true);
961 }
962
963
964
965 for (FileEntry fileEntry : message.getAttachmentsFileEntries()) {
966 PortletFileRepositoryUtil.restorePortletFileEntryFromTrash(
967 thread.getStatusByUserId(), fileEntry.getFileEntryId());
968 }
969
970
971
972 Indexer<MBMessage> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
973 MBMessage.class);
974
975 indexer.reindex(message);
976 }
977
978
979
980 for (long userId : userIds) {
981 mbStatsUserLocalService.updateStatsUser(groupId, userId);
982 }
983 }
984
985
989 @Deprecated
990 @Override
991 public void restoreDependentsFromTrash(
992 long groupId, long threadId, long trashEntryId)
993 throws PortalException {
994
995 restoreDependentsFromTrash(groupId, threadId);
996 }
997
998 @Override
999 public void restoreThreadFromTrash(long userId, long threadId)
1000 throws PortalException {
1001
1002
1003
1004 MBThread thread = getThread(threadId);
1005
1006 if (thread.getCategoryId() ==
1007 MBCategoryConstants.DISCUSSION_CATEGORY_ID) {
1008
1009 return;
1010 }
1011
1012 TrashEntry trashEntry = trashEntryLocalService.getEntry(
1013 MBThread.class.getName(), threadId);
1014
1015 updateStatus(userId, threadId, trashEntry.getStatus());
1016
1017
1018
1019 restoreDependentsFromTrash(thread.getGroupId(), threadId);
1020
1021
1022
1023 trashEntryLocalService.deleteEntry(trashEntry.getEntryId());
1024
1025
1026
1027 MBMessage message = mbMessageLocalService.getMBMessage(
1028 thread.getRootMessageId());
1029
1030 JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1031
1032 extraDataJSONObject.put("rootMessageId", thread.getRootMessageId());
1033 extraDataJSONObject.put("title", message.getSubject());
1034
1035 SocialActivityManagerUtil.addActivity(
1036 userId, thread, SocialActivityConstants.TYPE_RESTORE_FROM_TRASH,
1037 extraDataJSONObject.toString(), 0);
1038 }
1039
1040 @Override
1041 public Hits search(
1042 long groupId, long userId, long creatorUserId, int status,
1043 int start, int end)
1044 throws PortalException {
1045
1046 return search(groupId, userId, creatorUserId, 0, 0, status, start, end);
1047 }
1048
1049 @Override
1050 public Hits search(
1051 long groupId, long userId, long creatorUserId, long startDate,
1052 long endDate, int status, int start, int end)
1053 throws PortalException {
1054
1055 Indexer<MBThread> indexer = IndexerRegistryUtil.getIndexer(
1056 MBThread.class.getName());
1057
1058 SearchContext searchContext = new SearchContext();
1059
1060 searchContext.setAttribute(Field.STATUS, status);
1061
1062 if (endDate > 0) {
1063 searchContext.setAttribute("endDate", endDate);
1064 }
1065
1066 searchContext.setAttribute("paginationType", "none");
1067
1068 if (creatorUserId > 0) {
1069 searchContext.setAttribute(
1070 "participantUserId", String.valueOf(creatorUserId));
1071 }
1072
1073 if (startDate > 0) {
1074 searchContext.setAttribute("startDate", startDate);
1075 }
1076
1077 Group group = groupLocalService.getGroup(groupId);
1078
1079 searchContext.setCompanyId(group.getCompanyId());
1080
1081 searchContext.setEnd(end);
1082 searchContext.setGroupIds(new long[] {groupId});
1083 searchContext.setSorts(new Sort("lastPostDate", true));
1084 searchContext.setStart(start);
1085 searchContext.setUserId(userId);
1086
1087 return indexer.search(searchContext);
1088 }
1089
1090 @Override
1091 public MBThread splitThread(
1092 long userId, long messageId, String subject,
1093 ServiceContext serviceContext)
1094 throws PortalException {
1095
1096 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1097
1098 if (message.isRoot()) {
1099 throw new SplitThreadException(
1100 "Unable to split message " + messageId +
1101 " because it is a root message");
1102 }
1103
1104 MBCategory category = message.getCategory();
1105 MBThread oldThread = message.getThread();
1106 MBMessage rootMessage = mbMessagePersistence.findByPrimaryKey(
1107 oldThread.getRootMessageId());
1108 long oldAttachmentsFolderId = message.getAttachmentsFolderId();
1109
1110
1111
1112 mbMessageLocalService.updateAnswer(message, false, true);
1113
1114
1115
1116 MBThread thread = addThread(
1117 message.getCategoryId(), message, serviceContext);
1118
1119 mbThreadPersistence.update(oldThread);
1120
1121
1122
1123 if (Validator.isNotNull(subject)) {
1124 MBMessageDisplay messageDisplay =
1125 mbMessageLocalService.getMessageDisplay(
1126 userId, messageId, WorkflowConstants.STATUS_ANY,
1127 MBThreadConstants.THREAD_VIEW_TREE, false);
1128
1129 MBTreeWalker treeWalker = messageDisplay.getTreeWalker();
1130
1131 List<MBMessage> messages = treeWalker.getMessages();
1132
1133 int[] range = treeWalker.getChildrenRange(message);
1134
1135 for (int i = range[0]; i < range[1]; i++) {
1136 MBMessage curMessage = messages.get(i);
1137
1138 String oldSubject = message.getSubject();
1139 String curSubject = curMessage.getSubject();
1140
1141 if (oldSubject.startsWith("RE: ")) {
1142 curSubject = StringUtil.replace(
1143 curSubject, rootMessage.getSubject(), subject);
1144 }
1145 else {
1146 curSubject = StringUtil.replace(
1147 curSubject, oldSubject, subject);
1148 }
1149
1150 curMessage.setSubject(curSubject);
1151
1152 mbMessagePersistence.update(curMessage);
1153 }
1154
1155 message.setSubject(subject);
1156 }
1157
1158 message.setThreadId(thread.getThreadId());
1159 message.setRootMessageId(thread.getRootMessageId());
1160 message.setParentMessageId(0);
1161
1162 mbMessagePersistence.update(message);
1163
1164
1165
1166 moveAttachmentsFolders(
1167 message, oldAttachmentsFolderId, oldThread, thread, serviceContext);
1168
1169
1170
1171 if (!message.isDiscussion()) {
1172 Indexer<MBMessage> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1173 MBMessage.class);
1174
1175 indexer.reindex(message);
1176 }
1177
1178
1179
1180 moveChildrenMessages(message, category, oldThread.getThreadId());
1181
1182
1183
1184 MBUtil.updateThreadMessageCount(thread.getThreadId());
1185
1186
1187
1188 MBUtil.updateThreadMessageCount(oldThread.getThreadId());
1189
1190
1191
1192 if ((message.getCategoryId() !=
1193 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
1194 (message.getCategoryId() !=
1195 MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
1196
1197 MBUtil.updateCategoryThreadCount(category.getCategoryId());
1198 }
1199
1200
1201
1202 Indexer<MBThread> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1203 MBThread.class);
1204
1205 indexer.reindex(oldThread);
1206
1207 indexer.reindex(message.getThread());
1208
1209 return thread;
1210 }
1211
1212 @Override
1213 public MBThread updateMessageCount(long threadId) {
1214 MBThread mbThread = mbThreadPersistence.fetchByPrimaryKey(threadId);
1215
1216 if (mbThread == null) {
1217 return null;
1218 }
1219
1220 int messageCount = mbMessageLocalService.getThreadMessagesCount(
1221 threadId, WorkflowConstants.STATUS_APPROVED);
1222
1223 mbThread.setMessageCount(messageCount);
1224
1225 return mbThreadPersistence.update(mbThread);
1226 }
1227
1228 @Override
1229 public void updateQuestion(long threadId, boolean question)
1230 throws PortalException {
1231
1232 MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
1233
1234 if (thread.isQuestion() == question) {
1235 return;
1236 }
1237
1238 thread.setQuestion(question);
1239
1240 mbThreadPersistence.update(thread);
1241
1242 if (!question) {
1243 MBMessage message = mbMessagePersistence.findByPrimaryKey(
1244 thread.getRootMessageId());
1245
1246 mbMessageLocalService.updateAnswer(message, false, true);
1247 }
1248 }
1249
1250 @Override
1251 public MBThread updateStatus(long userId, long threadId, int status)
1252 throws PortalException {
1253
1254 MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
1255
1256
1257
1258 User user = userPersistence.findByPrimaryKey(userId);
1259
1260 thread.setStatus(status);
1261 thread.setStatusByUserId(user.getUserId());
1262 thread.setStatusByUserName(user.getFullName());
1263 thread.setStatusDate(new Date());
1264
1265 mbThreadPersistence.update(thread);
1266
1267
1268
1269 if (thread.getCategoryId() !=
1270 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
1271
1272
1273
1274 MBCategory category = mbCategoryPersistence.fetchByPrimaryKey(
1275 thread.getCategoryId());
1276
1277 if (category != null) {
1278 MBUtil.updateCategoryStatistics(category.getCategoryId());
1279 }
1280 }
1281
1282
1283
1284 Indexer<MBThread> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1285 MBThread.class);
1286
1287 indexer.reindex(thread);
1288
1289 return thread;
1290 }
1291
1292
1296 @Deprecated
1297 @Override
1298 public MBThread updateThread(long threadId, int viewCount)
1299 throws PortalException {
1300
1301 MBThread thread = mbThreadPersistence.findByPrimaryKey(threadId);
1302
1303 thread.setViewCount(viewCount);
1304
1305 mbThreadPersistence.update(thread);
1306
1307 return thread;
1308 }
1309
1310 protected void moveAttachmentsFolders(
1311 MBMessage message, long oldAttachmentsFolderId, MBThread oldThread,
1312 MBThread newThread, ServiceContext serviceContext)
1313 throws PortalException {
1314
1315 if (oldAttachmentsFolderId !=
1316 DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
1317
1318 Folder newThreadFolder = newThread.addAttachmentsFolder();
1319
1320 PortletFileRepositoryUtil.movePortletFolder(
1321 message.getGroupId(), message.getUserId(),
1322 oldAttachmentsFolderId, newThreadFolder.getFolderId(),
1323 serviceContext);
1324 }
1325
1326 List<MBMessage> childMessages = mbMessagePersistence.findByT_P(
1327 oldThread.getThreadId(), message.getMessageId());
1328
1329 for (MBMessage childMessage : childMessages) {
1330 moveAttachmentsFolders(
1331 childMessage, childMessage.getAttachmentsFolderId(), oldThread,
1332 newThread, serviceContext);
1333 }
1334 }
1335
1336 protected void moveChildrenMessages(
1337 MBMessage parentMessage, MBCategory category, long oldThreadId)
1338 throws PortalException {
1339
1340 List<MBMessage> messages = mbMessagePersistence.findByT_P(
1341 oldThreadId, parentMessage.getMessageId());
1342
1343 for (MBMessage message : messages) {
1344 message.setCategoryId(parentMessage.getCategoryId());
1345 message.setThreadId(parentMessage.getThreadId());
1346 message.setRootMessageId(parentMessage.getRootMessageId());
1347
1348 mbMessagePersistence.update(message);
1349
1350 if (!message.isDiscussion()) {
1351 Indexer<MBMessage> indexer =
1352 IndexerRegistryUtil.nullSafeGetIndexer(MBMessage.class);
1353
1354 indexer.reindex(message);
1355 }
1356
1357 moveChildrenMessages(message, category, oldThreadId);
1358 }
1359 }
1360
1361 }