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