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