001
014
015 package com.liferay.portlet.messageboards.service.impl;
016
017 import com.liferay.portal.kernel.comment.Comment;
018 import com.liferay.portal.kernel.exception.PortalException;
019 import com.liferay.portal.kernel.exception.SystemException;
020 import com.liferay.portal.kernel.json.JSONFactoryUtil;
021 import com.liferay.portal.kernel.json.JSONObject;
022 import com.liferay.portal.kernel.log.Log;
023 import com.liferay.portal.kernel.log.LogFactoryUtil;
024 import com.liferay.portal.kernel.notifications.UserNotificationDefinition;
025 import com.liferay.portal.kernel.parsers.bbcode.BBCodeTranslatorUtil;
026 import com.liferay.portal.kernel.portlet.PortletProvider;
027 import com.liferay.portal.kernel.portlet.PortletProviderUtil;
028 import com.liferay.portal.kernel.repository.model.FileEntry;
029 import com.liferay.portal.kernel.repository.model.Folder;
030 import com.liferay.portal.kernel.sanitizer.Sanitizer;
031 import com.liferay.portal.kernel.sanitizer.SanitizerUtil;
032 import com.liferay.portal.kernel.search.Indexable;
033 import com.liferay.portal.kernel.search.IndexableType;
034 import com.liferay.portal.kernel.search.Indexer;
035 import com.liferay.portal.kernel.search.IndexerRegistryUtil;
036 import com.liferay.portal.kernel.settings.LocalizedValuesMap;
037 import com.liferay.portal.kernel.social.SocialActivityManagerUtil;
038 import com.liferay.portal.kernel.systemevent.SystemEvent;
039 import com.liferay.portal.kernel.util.Constants;
040 import com.liferay.portal.kernel.util.ContentTypes;
041 import com.liferay.portal.kernel.util.GetterUtil;
042 import com.liferay.portal.kernel.util.ListUtil;
043 import com.liferay.portal.kernel.util.LocalizationUtil;
044 import com.liferay.portal.kernel.util.ObjectValuePair;
045 import com.liferay.portal.kernel.util.OrderByComparator;
046 import com.liferay.portal.kernel.util.ParamUtil;
047 import com.liferay.portal.kernel.util.PropsKeys;
048 import com.liferay.portal.kernel.util.StringPool;
049 import com.liferay.portal.kernel.util.StringUtil;
050 import com.liferay.portal.kernel.util.Validator;
051 import com.liferay.portal.kernel.util.WebKeys;
052 import com.liferay.portal.kernel.workflow.WorkflowConstants;
053 import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
054 import com.liferay.portal.kernel.workflow.WorkflowThreadLocal;
055 import com.liferay.portal.model.Company;
056 import com.liferay.portal.model.Group;
057 import com.liferay.portal.model.ModelHintsUtil;
058 import com.liferay.portal.model.ResourceConstants;
059 import com.liferay.portal.model.SystemEventConstants;
060 import com.liferay.portal.model.User;
061 import com.liferay.portal.portletfilerepository.PortletFileRepositoryUtil;
062 import com.liferay.portal.security.auth.PrincipalException;
063 import com.liferay.portal.security.permission.ActionKeys;
064 import com.liferay.portal.service.ServiceContext;
065 import com.liferay.portal.service.permission.ModelPermissions;
066 import com.liferay.portal.theme.ThemeDisplay;
067 import com.liferay.portal.util.LayoutURLUtil;
068 import com.liferay.portal.util.Portal;
069 import com.liferay.portal.util.PortalUtil;
070 import com.liferay.portal.util.PrefsPropsUtil;
071 import com.liferay.portal.util.PropsValues;
072 import com.liferay.portal.util.SubscriptionSender;
073 import com.liferay.portlet.asset.model.AssetEntry;
074 import com.liferay.portlet.asset.model.AssetLinkConstants;
075 import com.liferay.portlet.blogs.util.LinkbackProducerUtil;
076 import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
077 import com.liferay.portlet.messageboards.DiscussionMaxCommentsException;
078 import com.liferay.portlet.messageboards.MBGroupServiceSettings;
079 import com.liferay.portlet.messageboards.MessageBodyException;
080 import com.liferay.portlet.messageboards.MessageSubjectException;
081 import com.liferay.portlet.messageboards.NoSuchThreadException;
082 import com.liferay.portlet.messageboards.RequiredMessageException;
083 import com.liferay.portlet.messageboards.constants.MBConstants;
084 import com.liferay.portlet.messageboards.model.MBCategory;
085 import com.liferay.portlet.messageboards.model.MBCategoryConstants;
086 import com.liferay.portlet.messageboards.model.MBDiscussion;
087 import com.liferay.portlet.messageboards.model.MBMessage;
088 import com.liferay.portlet.messageboards.model.MBMessageConstants;
089 import com.liferay.portlet.messageboards.model.MBMessageDisplay;
090 import com.liferay.portlet.messageboards.model.MBThread;
091 import com.liferay.portlet.messageboards.model.MBThreadConstants;
092 import com.liferay.portlet.messageboards.model.impl.MBCategoryImpl;
093 import com.liferay.portlet.messageboards.model.impl.MBMessageDisplayImpl;
094 import com.liferay.portlet.messageboards.service.base.MBMessageLocalServiceBaseImpl;
095 import com.liferay.portlet.messageboards.service.permission.MBPermission;
096 import com.liferay.portlet.messageboards.social.MBActivityKeys;
097 import com.liferay.portlet.messageboards.util.MBSubscriptionSender;
098 import com.liferay.portlet.messageboards.util.MBUtil;
099 import com.liferay.portlet.messageboards.util.MailingListThreadLocal;
100 import com.liferay.portlet.messageboards.util.comparator.MessageCreateDateComparator;
101 import com.liferay.portlet.messageboards.util.comparator.MessageThreadComparator;
102 import com.liferay.portlet.messageboards.util.comparator.ThreadLastPostDateComparator;
103 import com.liferay.portlet.social.model.SocialActivityConstants;
104 import com.liferay.portlet.trash.util.TrashUtil;
105
106 import java.io.File;
107 import java.io.FileInputStream;
108 import java.io.FileNotFoundException;
109 import java.io.InputStream;
110 import java.io.Serializable;
111
112 import java.util.ArrayList;
113 import java.util.Collections;
114 import java.util.Comparator;
115 import java.util.Date;
116 import java.util.HashMap;
117 import java.util.List;
118 import java.util.Map;
119
120 import javax.portlet.PortletRequest;
121 import javax.portlet.PortletURL;
122
123 import javax.servlet.http.HttpServletRequest;
124
125 import net.htmlparser.jericho.Source;
126 import net.htmlparser.jericho.StartTag;
127
128
136 public class MBMessageLocalServiceImpl extends MBMessageLocalServiceBaseImpl {
137
138 @Override
139 public MBMessage addDiscussionMessage(
140 long userId, String userName, long groupId, String className,
141 long classPK, int workflowAction)
142 throws PortalException {
143
144 long threadId = 0;
145 long parentMessageId = MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID;
146 String subject = String.valueOf(classPK);
147 String body = subject;
148
149 ServiceContext serviceContext = new ServiceContext();
150
151 serviceContext.setWorkflowAction(workflowAction);
152
153 boolean workflowEnabled = WorkflowThreadLocal.isEnabled();
154
155 WorkflowThreadLocal.setEnabled(false);
156
157 try {
158 return addDiscussionMessage(
159 userId, userName, groupId, className, classPK, threadId,
160 parentMessageId, subject, body, serviceContext);
161 }
162 finally {
163 WorkflowThreadLocal.setEnabled(workflowEnabled);
164 }
165 }
166
167 @Override
168 public MBMessage addDiscussionMessage(
169 long userId, String userName, long groupId, String className,
170 long classPK, long threadId, long parentMessageId, String subject,
171 String body, ServiceContext serviceContext)
172 throws PortalException {
173
174
175
176 validateDiscussionMaxComments(className, classPK);
177
178 long categoryId = MBCategoryConstants.DISCUSSION_CATEGORY_ID;
179
180 if (Validator.isNull(subject)) {
181 if (Validator.isNotNull(body)) {
182 int pos = Math.min(body.length(), 50);
183
184 subject = body.substring(0, pos) + "...";
185 }
186 else {
187 throw new MessageBodyException("Body is null");
188 }
189 }
190
191 List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
192 Collections.emptyList();
193 boolean anonymous = false;
194 double priority = 0.0;
195 boolean allowPingbacks = false;
196
197 serviceContext.setAddGroupPermissions(true);
198 serviceContext.setAddGuestPermissions(true);
199 serviceContext.setAttribute("className", className);
200 serviceContext.setAttribute("classPK", String.valueOf(classPK));
201
202 Date now = new Date();
203
204 if (serviceContext.getCreateDate() == null) {
205 serviceContext.setCreateDate(now);
206 }
207
208 if (serviceContext.getModifiedDate() == null) {
209 serviceContext.setModifiedDate(now);
210 }
211
212 MBMessage message = addMessage(
213 userId, userName, groupId, categoryId, threadId, parentMessageId,
214 subject, body, PropsValues.DISCUSSION_COMMENTS_FORMAT,
215 inputStreamOVPs, anonymous, priority, allowPingbacks,
216 serviceContext);
217
218
219
220 if (parentMessageId == MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID) {
221 long classNameId = classNameLocalService.getClassNameId(className);
222
223 MBDiscussion discussion = mbDiscussionPersistence.fetchByC_C(
224 classNameId, classPK);
225
226 if (discussion == null) {
227 mbDiscussionLocalService.addDiscussion(
228 userId, groupId, classNameId, classPK,
229 message.getThreadId(), serviceContext);
230 }
231 }
232
233 return message;
234 }
235
236 @Override
237 public MBMessage addMessage(
238 long userId, String userName, long groupId, long categoryId,
239 long threadId, long parentMessageId, String subject, String body,
240 String format,
241 List<ObjectValuePair<String, InputStream>> inputStreamOVPs,
242 boolean anonymous, double priority, boolean allowPingbacks,
243 ServiceContext serviceContext)
244 throws PortalException {
245
246
247
248 User user = userPersistence.findByPrimaryKey(userId);
249 userName = user.isDefaultUser() ? userName : user.getFullName();
250 subject = ModelHintsUtil.trimString(
251 MBMessage.class.getName(), "subject", subject);
252
253 MBGroupServiceSettings mbGroupServiceSettings =
254 MBGroupServiceSettings.getInstance(groupId);
255
256 if (mbGroupServiceSettings != null) {
257 if (!mbGroupServiceSettings.isAllowAnonymousPosting()) {
258 if (anonymous || user.isDefaultUser()) {
259 throw new PrincipalException.MustHavePermission(
260 userId, ActionKeys.ADD_MESSAGE);
261 }
262 }
263 }
264
265 if (user.isDefaultUser()) {
266 anonymous = true;
267 }
268
269 Date now = new Date();
270
271 long messageId = counterLocalService.increment();
272
273 Map<String, Object> options = new HashMap<>();
274
275 boolean discussion = false;
276
277 if (categoryId == MBCategoryConstants.DISCUSSION_CATEGORY_ID) {
278 discussion = true;
279 }
280
281 options.put("discussion", discussion);
282
283 body = SanitizerUtil.sanitize(
284 user.getCompanyId(), groupId, userId, MBMessage.class.getName(),
285 messageId, "text/" + format, Sanitizer.MODE_ALL, body, options);
286
287 validate(subject, body);
288
289 subject = getSubject(subject, body);
290 body = getBody(subject, body);
291
292 MBMessage message = mbMessagePersistence.create(messageId);
293
294 message.setUuid(serviceContext.getUuid());
295 message.setGroupId(groupId);
296 message.setCompanyId(user.getCompanyId());
297 message.setUserId(user.getUserId());
298 message.setUserName(userName);
299 message.setCreateDate(serviceContext.getCreateDate(now));
300 message.setModifiedDate(serviceContext.getModifiedDate(now));
301
302 if (threadId > 0) {
303 message.setThreadId(threadId);
304 }
305
306 if (priority != MBThreadConstants.PRIORITY_NOT_GIVEN) {
307 message.setPriority(priority);
308 }
309
310 message.setAllowPingbacks(allowPingbacks);
311 message.setStatus(WorkflowConstants.STATUS_DRAFT);
312 message.setStatusByUserId(user.getUserId());
313 message.setStatusByUserName(userName);
314 message.setStatusDate(serviceContext.getModifiedDate(now));
315
316
317
318 if (parentMessageId != MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID) {
319 MBMessage parentMessage = mbMessagePersistence.fetchByPrimaryKey(
320 parentMessageId);
321
322 if (parentMessage == null) {
323 parentMessageId = MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID;
324 }
325 }
326
327 MBThread thread = null;
328
329 if (threadId > 0) {
330 thread = mbThreadPersistence.fetchByPrimaryKey(threadId);
331 }
332
333 if (thread == null) {
334 if (parentMessageId ==
335 MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID) {
336
337 thread = mbThreadLocalService.addThread(
338 categoryId, message, serviceContext);
339 }
340 else {
341 throw new NoSuchThreadException("{threadId=" + threadId + "}");
342 }
343 }
344
345 if ((priority != MBThreadConstants.PRIORITY_NOT_GIVEN) &&
346 (thread.getPriority() != priority)) {
347
348 thread.setPriority(priority);
349
350 mbThreadPersistence.update(thread);
351
352 updatePriorities(thread.getThreadId(), priority);
353 }
354
355
356
357 message.setCategoryId(categoryId);
358 message.setThreadId(thread.getThreadId());
359 message.setRootMessageId(thread.getRootMessageId());
360 message.setParentMessageId(parentMessageId);
361 message.setSubject(subject);
362 message.setBody(body);
363 message.setFormat(format);
364 message.setAnonymous(anonymous);
365
366 if (message.isDiscussion()) {
367 long classNameId = classNameLocalService.getClassNameId(
368 (String)serviceContext.getAttribute("className"));
369 long classPK = ParamUtil.getLong(serviceContext, "classPK");
370
371 message.setClassNameId(classNameId);
372 message.setClassPK(classPK);
373 }
374
375 message.setExpandoBridgeAttributes(serviceContext);
376
377 mbMessagePersistence.update(message);
378
379
380
381 if (ListUtil.isNotEmpty(inputStreamOVPs)) {
382 Folder folder = message.addAttachmentsFolder();
383
384 PortletFileRepositoryUtil.addPortletFileEntries(
385 message.getGroupId(), userId, MBMessage.class.getName(),
386 message.getMessageId(), MBConstants.SERVICE_NAME,
387 folder.getFolderId(), inputStreamOVPs);
388 }
389
390
391
392 if ((parentMessageId !=
393 MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID) &&
394 GetterUtil.getBoolean(
395 serviceContext.getAttribute("propagatePermissions"))) {
396
397 MBUtil.propagatePermissions(
398 message.getCompanyId(), groupId, parentMessageId,
399 serviceContext);
400 }
401
402 if (!message.isDiscussion()) {
403 if (user.isDefaultUser()) {
404 addMessageResources(message, true, true);
405 }
406 else if (serviceContext.isAddGroupPermissions() ||
407 serviceContext.isAddGuestPermissions()) {
408
409 addMessageResources(
410 message, serviceContext.isAddGroupPermissions(),
411 serviceContext.isAddGuestPermissions());
412 }
413 else {
414 addMessageResources(
415 message, serviceContext.getModelPermissions());
416 }
417 }
418
419
420
421 updateAsset(
422 userId, message, serviceContext.getAssetCategoryIds(),
423 serviceContext.getAssetTagNames(),
424 serviceContext.getAssetLinkEntryIds(),
425 serviceContext.isAssetEntryVisible());
426
427
428
429 startWorkflowInstance(userId, message, serviceContext);
430
431 return message;
432 }
433
434 @Override
435 public MBMessage addMessage(
436 long userId, String userName, long groupId, long categoryId,
437 String subject, String body, ServiceContext serviceContext)
438 throws PortalException {
439
440 List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
441 Collections.emptyList();
442
443 return addMessage(
444 userId, userName, groupId, categoryId, 0, 0, subject, body,
445 MBMessageConstants.DEFAULT_FORMAT, inputStreamOVPs, false, 0.0,
446 false, serviceContext);
447 }
448
449 @Override
450 public MBMessage addMessage(
451 long userId, String userName, long groupId, long categoryId,
452 String subject, String body, String format,
453 List<ObjectValuePair<String, InputStream>> inputStreamOVPs,
454 boolean anonymous, double priority, boolean allowPingbacks,
455 ServiceContext serviceContext)
456 throws PortalException {
457
458 long threadId = 0;
459 long parentMessageId = MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID;
460
461 return addMessage(
462 userId, userName, groupId, categoryId, threadId, parentMessageId,
463 subject, body, format, inputStreamOVPs, anonymous, priority,
464 allowPingbacks, serviceContext);
465 }
466
467 @Override
468 public MBMessage addMessage(
469 long userId, String userName, long groupId, long categoryId,
470 String subject, String body, String format, String fileName,
471 File file, boolean anonymous, double priority,
472 boolean allowPingbacks, ServiceContext serviceContext)
473 throws FileNotFoundException, PortalException {
474
475 List<ObjectValuePair<String, InputStream>> inputStreamOVPs =
476 new ArrayList<>(1);
477
478 InputStream inputStream = new FileInputStream(file);
479
480 ObjectValuePair<String, InputStream> inputStreamOVP =
481 new ObjectValuePair<>(fileName, inputStream);
482
483 inputStreamOVPs.add(inputStreamOVP);
484
485 return addMessage(
486 userId, userName, groupId, categoryId, 0, 0, subject, body, format,
487 inputStreamOVPs, anonymous, priority, allowPingbacks,
488 serviceContext);
489 }
490
491
495 @Deprecated
496 @Override
497 public MBMessage addMessage(
498 long userId, String userName, long categoryId, String subject,
499 String body, ServiceContext serviceContext)
500 throws PortalException {
501
502 long groupId = serviceContext.getScopeGroupId();
503
504 if (categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
505 MBCategory category = mbCategoryPersistence.findByPrimaryKey(
506 categoryId);
507
508 groupId = category.getGroupId();
509 }
510
511 return addMessage(
512 userId, userName, groupId, categoryId, subject, body,
513 serviceContext);
514 }
515
516 @Override
517 public void addMessageAttachment(
518 long userId, long messageId, String fileName, File file,
519 String mimeType)
520 throws PortalException {
521
522 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
523
524 Folder folder = message.addAttachmentsFolder();
525
526 PortletFileRepositoryUtil.addPortletFileEntry(
527 message.getGroupId(), userId, MBMessage.class.getName(),
528 message.getMessageId(), MBConstants.SERVICE_NAME,
529 folder.getFolderId(), file, fileName, mimeType, true);
530 }
531
532 @Override
533 public void addMessageResources(
534 long messageId, boolean addGroupPermissions,
535 boolean addGuestPermissions)
536 throws PortalException {
537
538 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
539
540 addMessageResources(message, addGroupPermissions, addGuestPermissions);
541 }
542
543 @Override
544 public void addMessageResources(
545 long messageId, ModelPermissions modelPermissions)
546 throws PortalException {
547
548 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
549
550 addMessageResources(message, modelPermissions);
551 }
552
553 @Override
554 public void addMessageResources(
555 MBMessage message, boolean addGroupPermissions,
556 boolean addGuestPermissions)
557 throws PortalException {
558
559 resourceLocalService.addResources(
560 message.getCompanyId(), message.getGroupId(), message.getUserId(),
561 MBMessage.class.getName(), message.getMessageId(), false,
562 addGroupPermissions, addGuestPermissions);
563 }
564
565 @Override
566 public void addMessageResources(
567 MBMessage message, ModelPermissions modelPermissions)
568 throws PortalException {
569
570 resourceLocalService.addModelResources(
571 message.getCompanyId(), message.getGroupId(), message.getUserId(),
572 MBMessage.class.getName(), message.getMessageId(),
573 modelPermissions);
574 }
575
576 @Indexable(type = IndexableType.DELETE)
577 @Override
578 public MBMessage deleteDiscussionMessage(long messageId)
579 throws PortalException {
580
581 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
582
583 SocialActivityManagerUtil.deleteActivities(message);
584
585 return mbMessageLocalService.deleteMessage(messageId);
586 }
587
588 @Override
589 public void deleteDiscussionMessages(String className, long classPK)
590 throws PortalException {
591
592 long classNameId = classNameLocalService.getClassNameId(className);
593
594 MBDiscussion discussion = mbDiscussionPersistence.fetchByC_C(
595 classNameId, classPK);
596
597 if (discussion == null) {
598 if (_log.isInfoEnabled()) {
599 _log.info(
600 "Unable to delete discussion message for class name " +
601 className + " and class PK " + classPK +
602 " because it does not exist");
603 }
604
605 return;
606 }
607
608 List<MBMessage> messages = mbMessagePersistence.findByT_P(
609 discussion.getThreadId(),
610 MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID, 0, 1);
611
612 if (!messages.isEmpty()) {
613 MBMessage message = messages.get(0);
614
615 SocialActivityManagerUtil.deleteActivities(message);
616
617 mbThreadLocalService.deleteThread(message.getThreadId());
618 }
619
620 mbDiscussionPersistence.remove(discussion);
621 }
622
623 @Indexable(type = IndexableType.DELETE)
624 @Override
625 public MBMessage deleteMessage(long messageId) throws PortalException {
626 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
627
628 return mbMessageLocalService.deleteMessage(message);
629 }
630
631 @Indexable(type = IndexableType.DELETE)
632 @Override
633 @SystemEvent(type = SystemEventConstants.TYPE_DELETE)
634 public MBMessage deleteMessage(MBMessage message) throws PortalException {
635
636
637
638 long folderId = message.getAttachmentsFolderId();
639
640 if (folderId != DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
641 PortletFileRepositoryUtil.deletePortletFolder(folderId);
642 }
643
644
645
646 int count = mbMessagePersistence.countByThreadId(message.getThreadId());
647
648 if (count == 1) {
649
650
651
652 long threadAttachmentsFolderId =
653 message.getThreadAttachmentsFolderId();
654
655 if (threadAttachmentsFolderId !=
656 DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
657
658 PortletFileRepositoryUtil.deletePortletFolder(
659 threadAttachmentsFolderId);
660 }
661
662
663
664 subscriptionLocalService.deleteSubscriptions(
665 message.getCompanyId(), MBThread.class.getName(),
666 message.getThreadId());
667
668
669
670 MBThread thread = mbThreadPersistence.findByPrimaryKey(
671 message.getThreadId());
672
673 mbThreadPersistence.remove(thread);
674
675
676
677 if ((message.getCategoryId() !=
678 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
679 (message.getCategoryId() !=
680 MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
681
682 MBUtil.updateCategoryStatistics(message.getCategoryId());
683 }
684
685
686
687 Indexer<MBThread> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
688 MBThread.class);
689
690 indexer.delete(thread);
691 }
692 else {
693 MBThread thread = mbThreadPersistence.findByPrimaryKey(
694 message.getThreadId());
695
696
697
698 if (thread.getRootMessageId() == message.getMessageId()) {
699 List<MBMessage> childrenMessages =
700 mbMessagePersistence.findByT_P(
701 message.getThreadId(), message.getMessageId());
702
703 if (childrenMessages.size() > 1) {
704 throw new RequiredMessageException(
705 String.valueOf(message.getMessageId()));
706 }
707 else if (childrenMessages.size() == 1) {
708 MBMessage childMessage = childrenMessages.get(0);
709
710 childMessage.setRootMessageId(childMessage.getMessageId());
711 childMessage.setParentMessageId(
712 MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID);
713
714 mbMessagePersistence.update(childMessage);
715
716 List<MBMessage> repliesMessages =
717 mbMessagePersistence.findByThreadReplies(
718 message.getThreadId());
719
720 for (MBMessage repliesMessage : repliesMessages) {
721 repliesMessage.setRootMessageId(
722 childMessage.getMessageId());
723
724 mbMessagePersistence.update(repliesMessage);
725 }
726
727 thread.setRootMessageId(childMessage.getMessageId());
728 thread.setRootMessageUserId(childMessage.getUserId());
729
730 mbThreadPersistence.update(thread);
731 }
732 }
733
734
735
736 else {
737 List<MBMessage> childrenMessages =
738 mbMessagePersistence.findByT_P(
739 message.getThreadId(), message.getMessageId());
740
741
742
743 if (!childrenMessages.isEmpty()) {
744 for (MBMessage childMessage : childrenMessages) {
745 childMessage.setParentMessageId(
746 message.getParentMessageId());
747
748 mbMessagePersistence.update(childMessage);
749 }
750 }
751 else if (message.getStatus() ==
752 WorkflowConstants.STATUS_APPROVED) {
753
754 MessageCreateDateComparator comparator =
755 new MessageCreateDateComparator(true);
756
757 MBMessage[] prevAndNextMessages =
758 mbMessagePersistence.findByT_S_PrevAndNext(
759 message.getMessageId(), thread.getThreadId(),
760 WorkflowConstants.STATUS_APPROVED, comparator);
761
762 if (prevAndNextMessages[2] == null) {
763 thread.setLastPostByUserId(
764 prevAndNextMessages[0].getUserId());
765 thread.setLastPostDate(
766 prevAndNextMessages[0].getModifiedDate());
767
768 mbThreadPersistence.update(thread);
769 }
770 }
771 }
772
773
774
775 if (message.isApproved()) {
776 MBUtil.updateThreadMessageCount(thread.getThreadId());
777 }
778
779
780
781 if ((message.getCategoryId() !=
782 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
783 (message.getCategoryId() !=
784 MBCategoryConstants.DISCUSSION_CATEGORY_ID) &&
785 !message.isDraft()) {
786
787 MBUtil.updateCategoryMessageCount(message.getCategoryId());
788 }
789
790
791
792 Indexer<MBThread> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
793 MBThread.class);
794
795 indexer.reindex(thread);
796 }
797
798
799
800 assetEntryLocalService.deleteEntry(
801 message.getWorkflowClassName(), message.getMessageId());
802
803
804
805 expandoRowLocalService.deleteRows(message.getMessageId());
806
807
808
809 ratingsStatsLocalService.deleteStats(
810 message.getWorkflowClassName(), message.getMessageId());
811
812
813
814 if (!message.isDiscussion()) {
815 resourceLocalService.deleteResource(
816 message.getCompanyId(), message.getWorkflowClassName(),
817 ResourceConstants.SCOPE_INDIVIDUAL, message.getMessageId());
818 }
819
820
821
822 mbMessagePersistence.remove(message);
823
824
825
826 if (!message.isDiscussion()) {
827 mbStatsUserLocalService.updateStatsUser(
828 message.getGroupId(), message.getUserId());
829 }
830
831
832
833 workflowInstanceLinkLocalService.deleteWorkflowInstanceLinks(
834 message.getCompanyId(), message.getGroupId(),
835 message.getWorkflowClassName(), message.getMessageId());
836
837 return message;
838 }
839
840 @Override
841 public void deleteMessageAttachment(long messageId, String fileName)
842 throws PortalException {
843
844 MBMessage message = getMessage(messageId);
845
846 long folderId = message.getAttachmentsFolderId();
847
848 if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
849 return;
850 }
851
852 PortletFileRepositoryUtil.deletePortletFileEntry(
853 message.getGroupId(), folderId, fileName);
854 }
855
856 @Override
857 public void deleteMessageAttachments(long messageId)
858 throws PortalException {
859
860 MBMessage message = getMessage(messageId);
861
862 long folderId = message.getAttachmentsFolderId();
863
864 if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
865 return;
866 }
867
868 PortletFileRepositoryUtil.deletePortletFileEntries(
869 message.getGroupId(), folderId);
870 }
871
872 @Override
873 public void emptyMessageAttachments(long messageId) throws PortalException {
874 MBMessage message = getMessage(messageId);
875
876 long folderId = message.getAttachmentsFolderId();
877
878 if (folderId == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
879 return;
880 }
881
882 PortletFileRepositoryUtil.deletePortletFileEntries(
883 message.getGroupId(), folderId, WorkflowConstants.STATUS_IN_TRASH);
884 }
885
886 @Override
887 public List<MBMessage> getCategoryMessages(
888 long groupId, long categoryId, int status, int start, int end) {
889
890 if (status == WorkflowConstants.STATUS_ANY) {
891 return mbMessagePersistence.findByG_C(
892 groupId, categoryId, start, end);
893 }
894 else {
895 return mbMessagePersistence.findByG_C_S(
896 groupId, categoryId, status, start, end);
897 }
898 }
899
900 @Override
901 public List<MBMessage> getCategoryMessages(
902 long groupId, long categoryId, int status, int start, int end,
903 OrderByComparator<MBMessage> obc) {
904
905 if (status == WorkflowConstants.STATUS_ANY) {
906 return mbMessagePersistence.findByG_C(
907 groupId, categoryId, start, end, obc);
908 }
909 else {
910 return mbMessagePersistence.findByG_C_S(
911 groupId, categoryId, status, start, end, obc);
912 }
913 }
914
915 @Override
916 public int getCategoryMessagesCount(
917 long groupId, long categoryId, int status) {
918
919 if (status == WorkflowConstants.STATUS_ANY) {
920 return mbMessagePersistence.countByG_C(groupId, categoryId);
921 }
922 else {
923 return mbMessagePersistence.countByG_C_S(
924 groupId, categoryId, status);
925 }
926 }
927
928 @Override
929 public List<MBMessage> getCompanyMessages(
930 long companyId, int status, int start, int end) {
931
932 if (status == WorkflowConstants.STATUS_ANY) {
933 return mbMessagePersistence.findByCompanyId(companyId, start, end);
934 }
935 else {
936 return mbMessagePersistence.findByC_S(
937 companyId, status, start, end);
938 }
939 }
940
941 @Override
942 public List<MBMessage> getCompanyMessages(
943 long companyId, int status, int start, int end,
944 OrderByComparator<MBMessage> obc) {
945
946 if (status == WorkflowConstants.STATUS_ANY) {
947 return mbMessagePersistence.findByCompanyId(
948 companyId, start, end, obc);
949 }
950 else {
951 return mbMessagePersistence.findByC_S(
952 companyId, status, start, end, obc);
953 }
954 }
955
956 @Override
957 public int getCompanyMessagesCount(long companyId, int status) {
958 if (status == WorkflowConstants.STATUS_ANY) {
959 return mbMessagePersistence.countByCompanyId(companyId);
960 }
961 else {
962 return mbMessagePersistence.countByC_S(companyId, status);
963 }
964 }
965
966 @Override
967 public MBMessageDisplay getDiscussionMessageDisplay(
968 long userId, long groupId, String className, long classPK,
969 int status)
970 throws PortalException {
971
972 return getDiscussionMessageDisplay(
973 userId, groupId, className, classPK, status,
974 new MessageThreadComparator());
975 }
976
977 @Override
978 public MBMessageDisplay getDiscussionMessageDisplay(
979 long userId, long groupId, String className, long classPK,
980 int status, Comparator<MBMessage> comparator)
981 throws PortalException {
982
983 long classNameId = classNameLocalService.getClassNameId(className);
984
985 MBMessage message = null;
986
987 MBDiscussion discussion = mbDiscussionPersistence.fetchByC_C(
988 classNameId, classPK);
989
990 if (discussion != null) {
991 message = mbMessagePersistence.findByT_P_First(
992 discussion.getThreadId(),
993 MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID, null);
994 }
995 else {
996 boolean workflowEnabled = WorkflowThreadLocal.isEnabled();
997
998 WorkflowThreadLocal.setEnabled(false);
999
1000 try {
1001 String subject = String.valueOf(classPK);
1002
1003
1004 message = addDiscussionMessage(
1005 userId, null, groupId, className, classPK, 0,
1006 MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID, subject,
1007 subject, new ServiceContext());
1008 }
1009 catch (SystemException se) {
1010 if (_log.isWarnEnabled()) {
1011 _log.warn(
1012 "Add failed, fetch {threadId=0, parentMessageId=" +
1013 MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID + "}");
1014 }
1015
1016 message = mbMessagePersistence.fetchByT_P_First(
1017 0, MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID, null);
1018
1019 if (message == null) {
1020 throw se;
1021 }
1022 }
1023 finally {
1024 WorkflowThreadLocal.setEnabled(workflowEnabled);
1025 }
1026 }
1027
1028 return getMessageDisplay(
1029 userId, message, status, MBThreadConstants.THREAD_VIEW_COMBINATION,
1030 false, comparator);
1031 }
1032
1033
1037 @Deprecated
1038 @Override
1039 public MBMessageDisplay getDiscussionMessageDisplay(
1040 long userId, long groupId, String className, long classPK,
1041 int status, String threadView)
1042 throws PortalException {
1043
1044 return getDiscussionMessageDisplay(
1045 userId, groupId, className, classPK, status);
1046 }
1047
1048 @Override
1049 public int getDiscussionMessagesCount(
1050 long classNameId, long classPK, int status) {
1051
1052 MBDiscussion discussion = mbDiscussionPersistence.fetchByC_C(
1053 classNameId, classPK);
1054
1055 if (discussion == null) {
1056 return 0;
1057 }
1058
1059 int count = 0;
1060
1061 if (status == WorkflowConstants.STATUS_ANY) {
1062 count = mbMessagePersistence.countByThreadId(
1063 discussion.getThreadId());
1064 }
1065 else {
1066 count = mbMessagePersistence.countByT_S(
1067 discussion.getThreadId(), status);
1068 }
1069
1070 if (count >= 1) {
1071 return count - 1;
1072 }
1073 else {
1074 return 0;
1075 }
1076 }
1077
1078 @Override
1079 public int getDiscussionMessagesCount(
1080 String className, long classPK, int status) {
1081
1082 long classNameId = classNameLocalService.getClassNameId(className);
1083
1084 return getDiscussionMessagesCount(classNameId, classPK, status);
1085 }
1086
1087 @Override
1088 public List<MBDiscussion> getDiscussions(String className) {
1089 long classNameId = classNameLocalService.getClassNameId(className);
1090
1091 return mbDiscussionPersistence.findByClassNameId(classNameId);
1092 }
1093
1094 @Override
1095 public List<MBMessage> getGroupMessages(
1096 long groupId, int status, int start, int end) {
1097
1098 if (status == WorkflowConstants.STATUS_ANY) {
1099 return mbMessagePersistence.findByGroupId(groupId, start, end);
1100 }
1101 else {
1102 return mbMessagePersistence.findByG_S(groupId, status, start, end);
1103 }
1104 }
1105
1106 @Override
1107 public List<MBMessage> getGroupMessages(
1108 long groupId, int status, int start, int end,
1109 OrderByComparator<MBMessage> obc) {
1110
1111 if (status == WorkflowConstants.STATUS_ANY) {
1112 return mbMessagePersistence.findByGroupId(groupId, start, end, obc);
1113 }
1114 else {
1115 return mbMessagePersistence.findByG_S(
1116 groupId, status, start, end, obc);
1117 }
1118 }
1119
1120 @Override
1121 public List<MBMessage> getGroupMessages(
1122 long groupId, long userId, int status, int start, int end) {
1123
1124 if (status == WorkflowConstants.STATUS_ANY) {
1125 return mbMessagePersistence.findByG_U(groupId, userId, start, end);
1126 }
1127 else {
1128 return mbMessagePersistence.findByG_U_S(
1129 groupId, userId, status, start, end);
1130 }
1131 }
1132
1133 @Override
1134 public List<MBMessage> getGroupMessages(
1135 long groupId, long userId, int status, int start, int end,
1136 OrderByComparator<MBMessage> obc) {
1137
1138 if (status == WorkflowConstants.STATUS_ANY) {
1139 return mbMessagePersistence.findByG_U(
1140 groupId, userId, start, end, obc);
1141 }
1142 else {
1143 return mbMessagePersistence.findByG_U_S(
1144 groupId, userId, status, start, end, obc);
1145 }
1146 }
1147
1148 @Override
1149 public int getGroupMessagesCount(long groupId, int status) {
1150 if (status == WorkflowConstants.STATUS_ANY) {
1151 return mbMessagePersistence.countByGroupId(groupId);
1152 }
1153 else {
1154 return mbMessagePersistence.countByG_S(groupId, status);
1155 }
1156 }
1157
1158 @Override
1159 public int getGroupMessagesCount(long groupId, long userId, int status) {
1160 if (status == WorkflowConstants.STATUS_ANY) {
1161 return mbMessagePersistence.countByG_U(groupId, userId);
1162 }
1163 else {
1164 return mbMessagePersistence.countByG_U_S(groupId, userId, status);
1165 }
1166 }
1167
1168 @Override
1169 public MBMessage getMessage(long messageId) throws PortalException {
1170 return mbMessagePersistence.findByPrimaryKey(messageId);
1171 }
1172
1173 @Override
1174 public MBMessageDisplay getMessageDisplay(
1175 long userId, long messageId, int status, String threadView,
1176 boolean includePrevAndNext)
1177 throws PortalException {
1178
1179 MBMessage message = getMessage(messageId);
1180
1181 return getMessageDisplay(
1182 userId, message, status, threadView, includePrevAndNext);
1183 }
1184
1185 @Override
1186 public MBMessageDisplay getMessageDisplay(
1187 long userId, MBMessage message, int status, String threadView,
1188 boolean includePrevAndNext)
1189 throws PortalException {
1190
1191 return getMessageDisplay(
1192 userId, message, status, threadView, includePrevAndNext,
1193 new MessageThreadComparator());
1194 }
1195
1196 @Override
1197 public MBMessageDisplay getMessageDisplay(
1198 long userId, MBMessage message, int status, String threadView,
1199 boolean includePrevAndNext, Comparator<MBMessage> comparator)
1200 throws PortalException {
1201
1202 MBCategory category = null;
1203
1204 if ((message.getCategoryId() !=
1205 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
1206 (message.getCategoryId() !=
1207 MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
1208
1209 category = mbCategoryPersistence.findByPrimaryKey(
1210 message.getCategoryId());
1211 }
1212 else {
1213 category = new MBCategoryImpl();
1214
1215 category.setCategoryId(message.getCategoryId());
1216 category.setDisplayStyle(MBCategoryConstants.DEFAULT_DISPLAY_STYLE);
1217 }
1218
1219 MBMessage parentMessage = null;
1220
1221 if (message.isReply()) {
1222 parentMessage = mbMessagePersistence.findByPrimaryKey(
1223 message.getParentMessageId());
1224 }
1225
1226 MBThread thread = mbThreadPersistence.findByPrimaryKey(
1227 message.getThreadId());
1228
1229 if (message.isApproved() && !message.isDiscussion()) {
1230 mbThreadLocalService.incrementViewCounter(thread.getThreadId(), 1);
1231
1232 SocialActivityManagerUtil.addActivity(
1233 userId, thread, SocialActivityConstants.TYPE_VIEW,
1234 StringPool.BLANK, 0);
1235 }
1236
1237 MBThread previousThread = null;
1238 MBThread nextThread = null;
1239
1240 if (message.isApproved() && includePrevAndNext) {
1241 ThreadLastPostDateComparator threadLastPostDateComparator =
1242 new ThreadLastPostDateComparator(false);
1243
1244 MBThread[] prevAndNextThreads = null;
1245
1246 if (status == WorkflowConstants.STATUS_ANY) {
1247 prevAndNextThreads =
1248 mbThreadPersistence.filterFindByG_C_NotS_PrevAndNext(
1249 message.getThreadId(), message.getGroupId(),
1250 message.getCategoryId(),
1251 WorkflowConstants.STATUS_IN_TRASH,
1252 threadLastPostDateComparator);
1253 }
1254 else {
1255 prevAndNextThreads =
1256 mbThreadPersistence.filterFindByG_C_S_PrevAndNext(
1257 message.getThreadId(), message.getGroupId(),
1258 message.getCategoryId(), status,
1259 threadLastPostDateComparator);
1260 }
1261
1262 previousThread = prevAndNextThreads[0];
1263 nextThread = prevAndNextThreads[2];
1264 }
1265
1266 return new MBMessageDisplayImpl(
1267 message, parentMessage, category, thread, previousThread,
1268 nextThread, status, threadView, this, comparator);
1269 }
1270
1271 @Override
1272 public List<MBMessage> getMessages(
1273 String className, long classPK, int status) {
1274
1275 long classNameId = classNameLocalService.getClassNameId(className);
1276
1277 if (status == WorkflowConstants.STATUS_ANY) {
1278 return mbMessagePersistence.findByC_C(classNameId, classPK);
1279 }
1280 else {
1281 return mbMessagePersistence.findByC_C_S(
1282 classNameId, classPK, status);
1283 }
1284 }
1285
1286 @Override
1287 public List<MBMessage> getNoAssetMessages() {
1288 return mbMessageFinder.findByNoAssets();
1289 }
1290
1291 @Override
1292 public int getPositionInThread(long messageId) throws PortalException {
1293 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1294
1295 return mbMessageFinder.countByC_T(
1296 message.getCreateDate(), message.getThreadId());
1297 }
1298
1299 @Override
1300 public List<MBMessage> getThreadMessages(long threadId, int status) {
1301 return getThreadMessages(
1302 threadId, status, new MessageThreadComparator());
1303 }
1304
1305 @Override
1306 public List<MBMessage> getThreadMessages(
1307 long threadId, int status, Comparator<MBMessage> comparator) {
1308
1309 List<MBMessage> messages = null;
1310
1311 if (status == WorkflowConstants.STATUS_ANY) {
1312 messages = mbMessagePersistence.findByThreadId(threadId);
1313 }
1314 else {
1315 messages = mbMessagePersistence.findByT_S(threadId, status);
1316 }
1317
1318 return ListUtil.sort(messages, comparator);
1319 }
1320
1321 @Override
1322 public List<MBMessage> getThreadMessages(
1323 long threadId, int status, int start, int end) {
1324
1325 if (status == WorkflowConstants.STATUS_ANY) {
1326 return mbMessagePersistence.findByThreadId(threadId, start, end);
1327 }
1328 else {
1329 return mbMessagePersistence.findByT_S(threadId, status, start, end);
1330 }
1331 }
1332
1333 @Override
1334 public int getThreadMessagesCount(long threadId, int status) {
1335 if (status == WorkflowConstants.STATUS_ANY) {
1336 return mbMessagePersistence.countByThreadId(threadId);
1337 }
1338 else {
1339 return mbMessagePersistence.countByT_S(threadId, status);
1340 }
1341 }
1342
1343 @Override
1344 public List<MBMessage> getThreadRepliesMessages(
1345 long threadId, int status, int start, int end) {
1346
1347 if (status == WorkflowConstants.STATUS_ANY) {
1348 return mbMessagePersistence.findByThreadReplies(
1349 threadId, start, end);
1350 }
1351 else {
1352 return mbMessagePersistence.findByTR_S(
1353 threadId, status, start, end);
1354 }
1355 }
1356
1357 @Override
1358 public List<MBMessage> getUserDiscussionMessages(
1359 long userId, long classNameId, long classPK, int status, int start,
1360 int end, OrderByComparator<MBMessage> obc) {
1361
1362 if (status == WorkflowConstants.STATUS_ANY) {
1363 return mbMessagePersistence.findByU_C_C(
1364 userId, classNameId, classPK, start, end, obc);
1365 }
1366 else {
1367 return mbMessagePersistence.findByU_C_C_S(
1368 userId, classNameId, classPK, status, start, end, obc);
1369 }
1370 }
1371
1372 @Override
1373 public List<MBMessage> getUserDiscussionMessages(
1374 long userId, long[] classNameIds, int status, int start, int end,
1375 OrderByComparator<MBMessage> obc) {
1376
1377 if (status == WorkflowConstants.STATUS_ANY) {
1378 return mbMessagePersistence.findByU_C(
1379 userId, classNameIds, start, end, obc);
1380 }
1381 else {
1382 return mbMessagePersistence.findByU_C_S(
1383 userId, classNameIds, status, start, end, obc);
1384 }
1385 }
1386
1387 @Override
1388 public List<MBMessage> getUserDiscussionMessages(
1389 long userId, String className, long classPK, int status, int start,
1390 int end, OrderByComparator<MBMessage> obc) {
1391
1392 long classNameId = classNameLocalService.getClassNameId(className);
1393
1394 return getUserDiscussionMessages(
1395 userId, classNameId, classPK, status, start, end, obc);
1396 }
1397
1398 @Override
1399 public int getUserDiscussionMessagesCount(
1400 long userId, long classNameId, long classPK, int status) {
1401
1402 if (status == WorkflowConstants.STATUS_ANY) {
1403 return mbMessagePersistence.countByU_C_C(
1404 userId, classNameId, classPK);
1405 }
1406 else {
1407 return mbMessagePersistence.countByU_C_C_S(
1408 userId, classNameId, classPK, status);
1409 }
1410 }
1411
1412 @Override
1413 public int getUserDiscussionMessagesCount(
1414 long userId, long[] classNameIds, int status) {
1415
1416 if (status == WorkflowConstants.STATUS_ANY) {
1417 return mbMessagePersistence.countByU_C(userId, classNameIds);
1418 }
1419 else {
1420 return mbMessagePersistence.countByU_C_S(
1421 userId, classNameIds, status);
1422 }
1423 }
1424
1425 @Override
1426 public int getUserDiscussionMessagesCount(
1427 long userId, String className, long classPK, int status) {
1428
1429 long classNameId = classNameLocalService.getClassNameId(className);
1430
1431 return getUserDiscussionMessagesCount(
1432 userId, classNameId, classPK, status);
1433 }
1434
1435 @Override
1436 public long moveMessageAttachmentToTrash(
1437 long userId, long messageId, String fileName)
1438 throws PortalException {
1439
1440 MBMessage message = getMessage(messageId);
1441
1442 long folderId = message.getAttachmentsFolderId();
1443
1444 FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
1445 message.getGroupId(), folderId, fileName);
1446
1447 PortletFileRepositoryUtil.movePortletFileEntryToTrash(
1448 userId, fileEntry.getFileEntryId());
1449
1450 return fileEntry.getFileEntryId();
1451 }
1452
1453 @Override
1454 public void restoreMessageAttachmentFromTrash(
1455 long userId, long messageId, String deletedFileName)
1456 throws PortalException {
1457
1458 MBMessage message = getMessage(messageId);
1459
1460 Folder folder = message.addAttachmentsFolder();
1461
1462 PortletFileRepositoryUtil.restorePortletFileEntryFromTrash(
1463 message.getGroupId(), userId, folder.getFolderId(),
1464 deletedFileName);
1465 }
1466
1467 @Override
1468 public void subscribeMessage(long userId, long messageId)
1469 throws PortalException {
1470
1471 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1472
1473 subscriptionLocalService.addSubscription(
1474 userId, message.getGroupId(), MBThread.class.getName(),
1475 message.getThreadId());
1476 }
1477
1478 @Override
1479 public void unsubscribeMessage(long userId, long messageId)
1480 throws PortalException {
1481
1482 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1483
1484 subscriptionLocalService.deleteSubscription(
1485 userId, MBThread.class.getName(), message.getThreadId());
1486 }
1487
1488 @Override
1489 public void updateAnswer(long messageId, boolean answer, boolean cascade)
1490 throws PortalException {
1491
1492 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1493
1494 updateAnswer(message, answer, cascade);
1495 }
1496
1497 @Override
1498 public void updateAnswer(MBMessage message, boolean answer, boolean cascade)
1499 throws PortalException {
1500
1501 if (message.isAnswer() != answer) {
1502 message.setAnswer(answer);
1503
1504 mbMessagePersistence.update(message);
1505 }
1506
1507 if (cascade) {
1508 List<MBMessage> messages = mbMessagePersistence.findByT_P(
1509 message.getThreadId(), message.getMessageId());
1510
1511 for (MBMessage curMessage : messages) {
1512 updateAnswer(curMessage, answer, cascade);
1513 }
1514 }
1515 }
1516
1517 @Override
1518 public void updateAsset(
1519 long userId, MBMessage message, long[] assetCategoryIds,
1520 String[] assetTagNames, long[] assetLinkEntryIds)
1521 throws PortalException {
1522
1523 updateAsset(
1524 userId, message, assetCategoryIds, assetTagNames, assetLinkEntryIds,
1525 true);
1526 }
1527
1528 @Override
1529 public MBMessage updateDiscussionMessage(
1530 long userId, long messageId, String className, long classPK,
1531 String subject, String body, ServiceContext serviceContext)
1532 throws PortalException {
1533
1534 if (Validator.isNull(subject)) {
1535 if (Validator.isNotNull(body)) {
1536 int pos = Math.min(body.length(), 50);
1537
1538 subject = body.substring(0, pos) + "...";
1539 }
1540 else {
1541 throw new MessageBodyException("Body is null");
1542 }
1543 }
1544
1545 List<ObjectValuePair<String, InputStream>> inputStreamOVPs = null;
1546 List<String> existingFiles = null;
1547 double priority = 0.0;
1548 boolean allowPingbacks = false;
1549
1550 serviceContext.setAttribute("className", className);
1551 serviceContext.setAttribute("classPK", String.valueOf(classPK));
1552
1553 return updateMessage(
1554 userId, messageId, subject, body, inputStreamOVPs, existingFiles,
1555 priority, allowPingbacks, serviceContext);
1556 }
1557
1558 @Override
1559 public MBMessage updateMessage(
1560 long userId, long messageId, String body,
1561 ServiceContext serviceContext)
1562 throws PortalException {
1563
1564 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1565
1566 return updateMessage(
1567 userId, messageId, message.getSubject(), body, null, null,
1568 message.getPriority(), message.isAllowPingbacks(), serviceContext);
1569 }
1570
1571 @Override
1572 public MBMessage updateMessage(
1573 long userId, long messageId, String subject, String body,
1574 List<ObjectValuePair<String, InputStream>> inputStreamOVPs,
1575 List<String> existingFiles, double priority, boolean allowPingbacks,
1576 ServiceContext serviceContext)
1577 throws PortalException {
1578
1579
1580
1581 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1582
1583 int oldStatus = message.getStatus();
1584
1585 Date modifiedDate = serviceContext.getModifiedDate(null);
1586 subject = ModelHintsUtil.trimString(
1587 MBMessage.class.getName(), "subject", subject);
1588
1589 Map<String, Object> options = new HashMap<>();
1590
1591 options.put("discussion", message.isDiscussion());
1592
1593 body = SanitizerUtil.sanitize(
1594 message.getCompanyId(), message.getGroupId(), userId,
1595 MBMessage.class.getName(), messageId, "text/" + message.getFormat(),
1596 Sanitizer.MODE_ALL, body, options);
1597
1598 validate(subject, body);
1599
1600 subject = getSubject(subject, body);
1601 body = getBody(subject, body);
1602
1603 message.setModifiedDate(modifiedDate);
1604 message.setSubject(subject);
1605 message.setBody(body);
1606 message.setAllowPingbacks(allowPingbacks);
1607
1608 if (priority != MBThreadConstants.PRIORITY_NOT_GIVEN) {
1609 message.setPriority(priority);
1610 }
1611
1612 MBThread thread = mbThreadPersistence.findByPrimaryKey(
1613 message.getThreadId());
1614
1615 if (serviceContext.getWorkflowAction() ==
1616 WorkflowConstants.ACTION_SAVE_DRAFT) {
1617
1618 if (!message.isDraft() && !message.isPending()) {
1619 message.setStatus(WorkflowConstants.STATUS_DRAFT);
1620
1621
1622
1623 User user = userPersistence.findByPrimaryKey(userId);
1624
1625 updateThreadStatus(
1626 thread, message, user, oldStatus, modifiedDate);
1627
1628
1629
1630 assetEntryLocalService.updateVisible(
1631 message.getWorkflowClassName(), message.getMessageId(),
1632 false);
1633
1634 if (!message.isDiscussion()) {
1635
1636
1637
1638 Indexer<MBMessage> indexer =
1639 IndexerRegistryUtil.nullSafeGetIndexer(MBMessage.class);
1640
1641 indexer.delete(message);
1642 }
1643 }
1644 }
1645
1646
1647
1648 if ((inputStreamOVPs != null) || (existingFiles != null)) {
1649 if (ListUtil.isNotEmpty(inputStreamOVPs) ||
1650 ListUtil.isNotEmpty(existingFiles)) {
1651
1652 List<FileEntry> fileEntries =
1653 message.getAttachmentsFileEntries();
1654
1655 for (FileEntry fileEntry : fileEntries) {
1656 String fileEntryId = String.valueOf(
1657 fileEntry.getFileEntryId());
1658
1659 if (!existingFiles.contains(fileEntryId)) {
1660 if (!TrashUtil.isTrashEnabled(message.getGroupId())) {
1661 deleteMessageAttachment(
1662 messageId, fileEntry.getTitle());
1663 }
1664 else {
1665 moveMessageAttachmentToTrash(
1666 userId, messageId, fileEntry.getTitle());
1667 }
1668 }
1669 }
1670
1671 Folder folder = message.addAttachmentsFolder();
1672
1673 PortletFileRepositoryUtil.addPortletFileEntries(
1674 message.getGroupId(), userId, MBMessage.class.getName(),
1675 message.getMessageId(), MBConstants.SERVICE_NAME,
1676 folder.getFolderId(), inputStreamOVPs);
1677 }
1678 else {
1679 if (TrashUtil.isTrashEnabled(message.getGroupId())) {
1680 List<FileEntry> fileEntries =
1681 message.getAttachmentsFileEntries();
1682
1683 for (FileEntry fileEntry : fileEntries) {
1684 moveMessageAttachmentToTrash(
1685 userId, messageId, fileEntry.getTitle());
1686 }
1687 }
1688 else {
1689 deleteMessageAttachments(message.getMessageId());
1690 }
1691 }
1692 }
1693
1694 message.setExpandoBridgeAttributes(serviceContext);
1695
1696 mbMessagePersistence.update(message);
1697
1698
1699
1700 if ((serviceContext.getWorkflowAction() ==
1701 WorkflowConstants.ACTION_SAVE_DRAFT) &&
1702 !message.isDiscussion()) {
1703
1704 mbStatsUserLocalService.updateStatsUser(
1705 message.getGroupId(), userId, message.getModifiedDate());
1706 }
1707
1708
1709
1710 if ((priority != MBThreadConstants.PRIORITY_NOT_GIVEN) &&
1711 (thread.getPriority() != priority)) {
1712
1713 thread.setPriority(priority);
1714
1715 mbThreadPersistence.update(thread);
1716
1717 updatePriorities(thread.getThreadId(), priority);
1718 }
1719
1720
1721
1722 updateAsset(
1723 userId, message, serviceContext.getAssetCategoryIds(),
1724 serviceContext.getAssetTagNames(),
1725 serviceContext.getAssetLinkEntryIds());
1726
1727
1728
1729 startWorkflowInstance(userId, message, serviceContext);
1730
1731 return message;
1732 }
1733
1734
1737 @Deprecated
1738 @Override
1739 public MBMessage updateMessage(long messageId, String body)
1740 throws PortalException {
1741
1742 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1743
1744 message.setBody(body);
1745
1746 mbMessagePersistence.update(message);
1747
1748 return message;
1749 }
1750
1751
1755 @Deprecated
1756 @Override
1757 public MBMessage updateStatus(
1758 long userId, long messageId, int status,
1759 ServiceContext serviceContext)
1760 throws PortalException {
1761
1762 return updateStatus(
1763 userId, messageId, status, serviceContext,
1764 new HashMap<String, Serializable>());
1765 }
1766
1767 @Override
1768 public MBMessage updateStatus(
1769 long userId, long messageId, int status,
1770 ServiceContext serviceContext,
1771 Map<String, Serializable> workflowContext)
1772 throws PortalException {
1773
1774
1775
1776 MBMessage message = getMessage(messageId);
1777
1778 int oldStatus = message.getStatus();
1779
1780 User user = userPersistence.findByPrimaryKey(userId);
1781 Date now = new Date();
1782
1783 Date modifiedDate = serviceContext.getModifiedDate(now);
1784
1785 message.setStatus(status);
1786 message.setStatusByUserId(userId);
1787 message.setStatusByUserName(user.getFullName());
1788 message.setStatusDate(modifiedDate);
1789
1790 mbMessagePersistence.update(message);
1791
1792
1793
1794 MBThread thread = mbThreadPersistence.findByPrimaryKey(
1795 message.getThreadId());
1796
1797 updateThreadStatus(thread, message, user, oldStatus, modifiedDate);
1798
1799 Indexer<MBMessage> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1800 MBMessage.class);
1801
1802 if (status == WorkflowConstants.STATUS_APPROVED) {
1803 if (oldStatus != WorkflowConstants.STATUS_APPROVED) {
1804
1805
1806
1807 if (serviceContext.isAssetEntryVisible() &&
1808 ((message.getClassNameId() == 0) ||
1809 (message.getParentMessageId() != 0))) {
1810
1811 Date publishDate = null;
1812
1813 AssetEntry assetEntry = assetEntryLocalService.fetchEntry(
1814 message.getWorkflowClassName(), message.getMessageId());
1815
1816 if ((assetEntry != null) &&
1817 (assetEntry.getPublishDate() != null)) {
1818
1819 publishDate = assetEntry.getPublishDate();
1820 }
1821 else {
1822 publishDate = now;
1823
1824 serviceContext.setCommand(Constants.ADD);
1825 }
1826
1827 assetEntryLocalService.updateEntry(
1828 message.getWorkflowClassName(), message.getMessageId(),
1829 publishDate, true);
1830 }
1831
1832 if (serviceContext.isCommandAdd()) {
1833
1834
1835
1836 JSONObject extraDataJSONObject =
1837 JSONFactoryUtil.createJSONObject();
1838
1839 extraDataJSONObject.put("title", message.getSubject());
1840
1841 if (!message.isDiscussion() ) {
1842 if (!message.isAnonymous() && !user.isDefaultUser()) {
1843 long receiverUserId = 0;
1844
1845 MBMessage parentMessage =
1846 mbMessagePersistence.fetchByPrimaryKey(
1847 message.getParentMessageId());
1848
1849 if (parentMessage != null) {
1850 receiverUserId = parentMessage.getUserId();
1851 }
1852
1853 SocialActivityManagerUtil.addActivity(
1854 message.getUserId(), message,
1855 MBActivityKeys.ADD_MESSAGE,
1856 extraDataJSONObject.toString(), receiverUserId);
1857
1858 if ((parentMessage != null) &&
1859 (receiverUserId != message.getUserId())) {
1860
1861 SocialActivityManagerUtil.addActivity(
1862 message.getUserId(), parentMessage,
1863 MBActivityKeys.REPLY_MESSAGE,
1864 extraDataJSONObject.toString(), 0);
1865 }
1866 }
1867 }
1868 else {
1869 String className = (String)serviceContext.getAttribute(
1870 "className");
1871 long classPK = ParamUtil.getLong(
1872 serviceContext, "classPK");
1873 long parentMessageId = message.getParentMessageId();
1874
1875 if (parentMessageId !=
1876 MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID) {
1877
1878 AssetEntry assetEntry =
1879 assetEntryLocalService.fetchEntry(
1880 className, classPK);
1881
1882 if (assetEntry != null) {
1883 extraDataJSONObject.put(
1884 "messageId", message.getMessageId());
1885
1886 SocialActivityManagerUtil.addActivity(
1887 message.getUserId(), assetEntry,
1888 SocialActivityConstants.TYPE_ADD_COMMENT,
1889 extraDataJSONObject.toString(),
1890 assetEntry.getUserId());
1891 }
1892 }
1893 }
1894 }
1895 }
1896
1897
1898
1899 notifySubscribers(
1900 userId, (MBMessage)message.clone(),
1901 (String)workflowContext.get(WorkflowConstants.CONTEXT_URL),
1902 serviceContext);
1903
1904
1905
1906 indexer.reindex(message);
1907
1908
1909
1910 pingPingback(message, serviceContext);
1911 }
1912 else if (oldStatus == WorkflowConstants.STATUS_APPROVED) {
1913
1914
1915
1916 assetEntryLocalService.updateVisible(
1917 message.getWorkflowClassName(), message.getMessageId(), false);
1918
1919
1920
1921 indexer.delete(message);
1922 }
1923
1924
1925
1926 if (!message.isDiscussion()) {
1927 mbStatsUserLocalService.updateStatsUser(
1928 message.getGroupId(), userId,
1929 serviceContext.getModifiedDate(now));
1930 }
1931
1932 return message;
1933 }
1934
1935 @Override
1936 public void updateUserName(long userId, String userName) {
1937 List<MBMessage> messages = mbMessagePersistence.findByUserId(userId);
1938
1939 for (MBMessage message : messages) {
1940 message.setUserName(userName);
1941
1942 mbMessagePersistence.update(message);
1943 }
1944 }
1945
1946 protected String getBody(String subject, String body) {
1947 if (Validator.isNull(body)) {
1948 return subject;
1949 }
1950
1951 return body;
1952 }
1953
1954 protected String getMessageURL(
1955 MBMessage message, ServiceContext serviceContext)
1956 throws PortalException {
1957
1958 String entryURL = GetterUtil.getString(
1959 serviceContext.getAttribute("entryURL"));
1960
1961 if (Validator.isNotNull(entryURL)) {
1962 return entryURL;
1963 }
1964
1965 HttpServletRequest request = serviceContext.getRequest();
1966
1967 if (request == null) {
1968 if (Validator.isNull(serviceContext.getLayoutFullURL())) {
1969 return StringPool.BLANK;
1970 }
1971
1972 return serviceContext.getLayoutFullURL() +
1973 Portal.FRIENDLY_URL_SEPARATOR + "message_boards/view_message/" +
1974 message.getMessageId();
1975 }
1976
1977 String portletId = PortletProviderUtil.getPortletId(
1978 MBMessage.class.getName(), PortletProvider.Action.VIEW);
1979
1980 String layoutURL = LayoutURLUtil.getLayoutURL(
1981 message.getGroupId(), portletId, serviceContext);
1982
1983 if (Validator.isNotNull(layoutURL)) {
1984 return layoutURL + Portal.FRIENDLY_URL_SEPARATOR +
1985 "message_boards/view_message/" + message.getMessageId();
1986 }
1987 else {
1988 portletId = PortletProviderUtil.getPortletId(
1989 MBMessage.class.getName(), PortletProvider.Action.MANAGE);
1990
1991 PortletURL portletURL = PortalUtil.getControlPanelPortletURL(
1992 request, portletId, PortletRequest.RENDER_PHASE);
1993
1994 portletURL.setParameter(
1995 "mvcRenderCommandName", "/message_boards/view_message");
1996 portletURL.setParameter(
1997 "messageId", String.valueOf(message.getMessageId()));
1998
1999 return portletURL.toString();
2000 }
2001 }
2002
2003 protected String getSubject(String subject, String body) {
2004 if (Validator.isNull(subject)) {
2005 return StringUtil.shorten(body);
2006 }
2007
2008 return subject;
2009 }
2010
2011 protected MBSubscriptionSender getSubscriptionSender(
2012 long userId, MBMessage message, String messageURL, String entryTitle,
2013 boolean htmlFormat, String messageBody, String categoryName,
2014 String inReplyTo, String fromName, String fromAddress,
2015 String replyToAddress, String emailAddress, String fullName,
2016 LocalizedValuesMap subjectLocalizedValuesMap,
2017 LocalizedValuesMap bodyLocalizedValuesMap,
2018 ServiceContext serviceContext) {
2019
2020 MBSubscriptionSender subscriptionSender = new MBSubscriptionSender(
2021 MBPermission.RESOURCE_NAME);
2022
2023 subscriptionSender.setBulk(PropsValues.MESSAGE_BOARDS_EMAIL_BULK);
2024 subscriptionSender.setClassName(message.getModelClassName());
2025 subscriptionSender.setClassPK(message.getMessageId());
2026 subscriptionSender.setCompanyId(message.getCompanyId());
2027 subscriptionSender.setContextAttribute(
2028 "[$MESSAGE_BODY$]", messageBody, false);
2029 subscriptionSender.setContextAttributes(
2030 "[$CATEGORY_NAME$]", categoryName, "[$MAILING_LIST_ADDRESS$]",
2031 replyToAddress, "[$MESSAGE_ID$]", message.getMessageId(),
2032 "[$MESSAGE_SUBJECT$]", entryTitle, "[$MESSAGE_URL$]", messageURL,
2033 "[$MESSAGE_USER_ADDRESS$]", emailAddress, "[$MESSAGE_USER_NAME$]",
2034 fullName);
2035 subscriptionSender.setCurrentUserId(userId);
2036 subscriptionSender.setEntryTitle(entryTitle);
2037 subscriptionSender.setEntryURL(messageURL);
2038 subscriptionSender.setFrom(fromAddress, fromName);
2039 subscriptionSender.setHtmlFormat(htmlFormat);
2040 subscriptionSender.setInReplyTo(inReplyTo);
2041
2042 if (bodyLocalizedValuesMap != null) {
2043 subscriptionSender.setLocalizedBodyMap(
2044 LocalizationUtil.getMap(bodyLocalizedValuesMap));
2045 }
2046
2047 if (subjectLocalizedValuesMap != null) {
2048 subscriptionSender.setLocalizedSubjectMap(
2049 LocalizationUtil.getMap(subjectLocalizedValuesMap));
2050 }
2051
2052 Date modifiedDate = message.getModifiedDate();
2053
2054 subscriptionSender.setMailId(
2055 MBUtil.MESSAGE_POP_PORTLET_PREFIX, message.getCategoryId(),
2056 message.getMessageId(), modifiedDate.getTime());
2057
2058 int notificationType =
2059 UserNotificationDefinition.NOTIFICATION_TYPE_ADD_ENTRY;
2060
2061 if (serviceContext.isCommandUpdate()) {
2062 notificationType =
2063 UserNotificationDefinition.NOTIFICATION_TYPE_UPDATE_ENTRY;
2064 }
2065
2066 subscriptionSender.setNotificationType(notificationType);
2067
2068 String portletId = PortletProviderUtil.getPortletId(
2069 MBMessage.class.getName(), PortletProvider.Action.VIEW);
2070
2071 subscriptionSender.setPortletId(portletId);
2072
2073 subscriptionSender.setReplyToAddress(replyToAddress);
2074 subscriptionSender.setScopeGroupId(message.getGroupId());
2075 subscriptionSender.setServiceContext(serviceContext);
2076 subscriptionSender.setUniqueMailId(false);
2077
2078 return subscriptionSender;
2079 }
2080
2081 protected void notifyDiscussionSubscribers(
2082 long userId, MBMessage message, ServiceContext serviceContext)
2083 throws PortalException {
2084
2085 if (!PrefsPropsUtil.getBoolean(
2086 message.getCompanyId(),
2087 PropsKeys.DISCUSSION_EMAIL_COMMENTS_ADDED_ENABLED)) {
2088
2089 return;
2090 }
2091
2092 MBDiscussion mbDiscussion =
2093 mbDiscussionLocalService.getThreadDiscussion(message.getThreadId());
2094
2095 String contentURL = (String)serviceContext.getAttribute("contentURL");
2096
2097 String userAddress = StringPool.BLANK;
2098 String userName = (String)serviceContext.getAttribute(
2099 "pingbackUserName");
2100
2101 if (Validator.isNull(userName)) {
2102 userAddress = PortalUtil.getUserEmailAddress(message.getUserId());
2103 userName = PortalUtil.getUserName(
2104 message.getUserId(), StringPool.BLANK);
2105 }
2106
2107 String fromName = PrefsPropsUtil.getString(
2108 message.getCompanyId(), PropsKeys.ADMIN_EMAIL_FROM_NAME);
2109 String fromAddress = PrefsPropsUtil.getString(
2110 message.getCompanyId(), PropsKeys.ADMIN_EMAIL_FROM_ADDRESS);
2111
2112 String subject = PrefsPropsUtil.getContent(
2113 message.getCompanyId(), PropsKeys.DISCUSSION_EMAIL_SUBJECT);
2114 String body = PrefsPropsUtil.getContent(
2115 message.getCompanyId(), PropsKeys.DISCUSSION_EMAIL_BODY);
2116
2117 SubscriptionSender subscriptionSender = new SubscriptionSender();
2118
2119 subscriptionSender.setBody(body);
2120 subscriptionSender.setCompanyId(message.getCompanyId());
2121 subscriptionSender.setClassName(MBDiscussion.class.getName());
2122 subscriptionSender.setClassPK(mbDiscussion.getDiscussionId());
2123 subscriptionSender.setContextAttribute(
2124 "[$COMMENTS_BODY$]", message.getBody(true), false);
2125 subscriptionSender.setContextAttributes(
2126 "[$COMMENTS_USER_ADDRESS$]", userAddress, "[$COMMENTS_USER_NAME$]",
2127 userName, "[$CONTENT_URL$]", contentURL);
2128 subscriptionSender.setCurrentUserId(userId);
2129 subscriptionSender.setEntryTitle(message.getBody());
2130 subscriptionSender.setEntryURL(contentURL);
2131 subscriptionSender.setFrom(fromAddress, fromName);
2132 subscriptionSender.setHtmlFormat(true);
2133
2134 Date modifiedDate = message.getModifiedDate();
2135
2136 subscriptionSender.setMailId(
2137 "mb_discussion", message.getCategoryId(), message.getMessageId(),
2138 modifiedDate.getTime());
2139
2140 int notificationType =
2141 UserNotificationDefinition.NOTIFICATION_TYPE_ADD_ENTRY;
2142
2143 if (serviceContext.isCommandUpdate()) {
2144 notificationType =
2145 UserNotificationDefinition.NOTIFICATION_TYPE_UPDATE_ENTRY;
2146 }
2147
2148 subscriptionSender.setNotificationType(notificationType);
2149
2150 String portletId = PortletProviderUtil.getPortletId(
2151 Comment.class.getName(), PortletProvider.Action.VIEW);
2152
2153 subscriptionSender.setPortletId(portletId);
2154
2155 subscriptionSender.setScopeGroupId(message.getGroupId());
2156 subscriptionSender.setServiceContext(serviceContext);
2157 subscriptionSender.setSubject(subject);
2158 subscriptionSender.setUniqueMailId(false);
2159
2160 String className = (String)serviceContext.getAttribute("className");
2161 long classPK = ParamUtil.getLong(serviceContext, "classPK");
2162
2163 subscriptionSender.addPersistedSubscribers(className, classPK);
2164
2165 subscriptionSender.flushNotificationsAsync();
2166 }
2167
2168 protected void notifySubscribers(
2169 long userId, MBMessage message, String messageURL,
2170 ServiceContext serviceContext)
2171 throws PortalException {
2172
2173 if (!message.isApproved() || Validator.isNull(messageURL)) {
2174 return;
2175 }
2176
2177 if (message.isDiscussion()) {
2178 try {
2179 notifyDiscussionSubscribers(userId, message, serviceContext);
2180 }
2181 catch (Exception e) {
2182 _log.error(e, e);
2183 }
2184
2185 return;
2186 }
2187
2188 MBGroupServiceSettings mbGroupServiceSettings =
2189 MBGroupServiceSettings.getInstance(message.getGroupId());
2190
2191 if (serviceContext.isCommandAdd() &&
2192 mbGroupServiceSettings.isEmailMessageAddedEnabled()) {
2193 }
2194 else if (serviceContext.isCommandUpdate() &&
2195 mbGroupServiceSettings.isEmailMessageUpdatedEnabled()) {
2196 }
2197 else {
2198 return;
2199 }
2200
2201 Company company = companyPersistence.findByPrimaryKey(
2202 message.getCompanyId());
2203
2204 Group group = groupPersistence.findByPrimaryKey(message.getGroupId());
2205
2206 String emailAddress = PortalUtil.getUserEmailAddress(
2207 message.getUserId());
2208 String fullName = PortalUtil.getUserName(
2209 message.getUserId(), message.getUserName());
2210
2211 if (message.isAnonymous()) {
2212 emailAddress = StringPool.BLANK;
2213 fullName = serviceContext.translate("anonymous");
2214 }
2215
2216 MBCategory category = message.getCategory();
2217
2218 String categoryName = category.getName();
2219
2220 if (category.getCategoryId() ==
2221 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
2222
2223 categoryName = serviceContext.translate("message-boards-home");
2224
2225 categoryName += " - " + group.getDescriptiveName();
2226 }
2227
2228 List<Long> categoryIds = new ArrayList<>();
2229
2230 categoryIds.add(message.getCategoryId());
2231
2232 if (message.getCategoryId() !=
2233 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
2234
2235 categoryIds.addAll(category.getAncestorCategoryIds());
2236 }
2237
2238 String entryTitle = message.getSubject();
2239
2240 String fromName = mbGroupServiceSettings.getEmailFromName();
2241 String fromAddress = mbGroupServiceSettings.getEmailFromAddress();
2242
2243 String replyToAddress = StringPool.BLANK;
2244
2245 if (PropsValues.POP_SERVER_NOTIFICATIONS_ENABLED) {
2246 replyToAddress = MBUtil.getReplyToAddress(
2247 message.getCategoryId(), message.getMessageId(),
2248 company.getMx(), fromAddress);
2249 }
2250
2251 LocalizedValuesMap subjectLocalizedValuesMap = null;
2252 LocalizedValuesMap bodyLocalizedValuesMap = null;
2253
2254 if (serviceContext.isCommandUpdate()) {
2255 subjectLocalizedValuesMap =
2256 mbGroupServiceSettings.getEmailMessageUpdatedSubject();
2257 bodyLocalizedValuesMap =
2258 mbGroupServiceSettings.getEmailMessageUpdatedBody();
2259 }
2260 else {
2261 subjectLocalizedValuesMap =
2262 mbGroupServiceSettings.getEmailMessageAddedSubject();
2263 bodyLocalizedValuesMap =
2264 mbGroupServiceSettings.getEmailMessageAddedBody();
2265 }
2266
2267 boolean htmlFormat = mbGroupServiceSettings.isEmailHtmlFormat();
2268
2269 String messageBody = message.getBody();
2270
2271 if (htmlFormat && message.isFormatBBCode()) {
2272 try {
2273 messageBody = BBCodeTranslatorUtil.getHTML(messageBody);
2274
2275 HttpServletRequest request = serviceContext.getRequest();
2276
2277 if (request != null) {
2278 ThemeDisplay themeDisplay =
2279 (ThemeDisplay)request.getAttribute(
2280 WebKeys.THEME_DISPLAY);
2281
2282 messageBody = MBUtil.replaceMessageBodyPaths(
2283 themeDisplay, messageBody);
2284 }
2285 }
2286 catch (Exception e) {
2287 _log.error(
2288 "Could not parse message " + message.getMessageId() +
2289 " " + e.getMessage());
2290 }
2291 }
2292
2293 String inReplyTo = null;
2294
2295 if (message.getParentMessageId() !=
2296 MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID) {
2297
2298 MBMessage parentMessage = mbMessageLocalService.getMessage(
2299 message.getParentMessageId());
2300
2301 Date modifiedDate = parentMessage.getModifiedDate();
2302
2303 inReplyTo = PortalUtil.getMailId(
2304 company.getMx(), MBUtil.MESSAGE_POP_PORTLET_PREFIX,
2305 message.getCategoryId(), parentMessage.getMessageId(),
2306 modifiedDate.getTime());
2307 }
2308
2309 SubscriptionSender subscriptionSender = getSubscriptionSender(
2310 userId, message, messageURL, entryTitle, htmlFormat, messageBody,
2311 categoryName, inReplyTo, fromName, fromAddress, replyToAddress,
2312 emailAddress, fullName, subjectLocalizedValuesMap,
2313 bodyLocalizedValuesMap, serviceContext);
2314
2315 subscriptionSender.addPersistedSubscribers(
2316 MBCategory.class.getName(), message.getGroupId());
2317
2318 for (long categoryId : categoryIds) {
2319 if (categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
2320 subscriptionSender.addPersistedSubscribers(
2321 MBCategory.class.getName(), categoryId);
2322 }
2323 }
2324
2325 subscriptionSender.addPersistedSubscribers(
2326 MBThread.class.getName(), message.getThreadId());
2327
2328 subscriptionSender.flushNotificationsAsync();
2329
2330 if (!MailingListThreadLocal.isSourceMailingList()) {
2331 for (long categoryId : categoryIds) {
2332 MBSubscriptionSender sourceMailingListSubscriptionSender =
2333 getSubscriptionSender(
2334 userId, message, messageURL, entryTitle, htmlFormat,
2335 messageBody, categoryName, inReplyTo, fromName,
2336 fromAddress, replyToAddress, emailAddress, fullName,
2337 subjectLocalizedValuesMap, bodyLocalizedValuesMap,
2338 serviceContext);
2339
2340 sourceMailingListSubscriptionSender.setBulk(false);
2341
2342 sourceMailingListSubscriptionSender.addMailingListSubscriber(
2343 message.getGroupId(), categoryId);
2344
2345 sourceMailingListSubscriptionSender.flushNotificationsAsync();
2346 }
2347 }
2348 }
2349
2350 protected void pingPingback(
2351 MBMessage message, ServiceContext serviceContext) {
2352
2353 if (!PropsValues.BLOGS_PINGBACK_ENABLED ||
2354 !message.isAllowPingbacks() || !message.isApproved()) {
2355
2356 return;
2357 }
2358
2359 String layoutFullURL = serviceContext.getLayoutFullURL();
2360
2361 if (Validator.isNull(layoutFullURL)) {
2362 return;
2363 }
2364
2365 String sourceUri =
2366 layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR +
2367 "message_boards/view_message/" + message.getMessageId();
2368
2369 Source source = new Source(message.getBody(true));
2370
2371 List<StartTag> startTags = source.getAllStartTags("a");
2372
2373 for (StartTag startTag : startTags) {
2374 String targetUri = startTag.getAttributeValue("href");
2375
2376 if (Validator.isNotNull(targetUri)) {
2377 try {
2378 LinkbackProducerUtil.sendPingback(sourceUri, targetUri);
2379 }
2380 catch (Exception e) {
2381 _log.error("Error while sending pingback " + targetUri, e);
2382 }
2383 }
2384 }
2385 }
2386
2387 protected void startWorkflowInstance(
2388 long userId, MBMessage message, ServiceContext serviceContext)
2389 throws PortalException {
2390
2391 Map<String, Serializable> workflowContext = new HashMap<>();
2392
2393 workflowContext.put(
2394 WorkflowConstants.CONTEXT_URL,
2395 getMessageURL(message, serviceContext));
2396
2397 WorkflowHandlerRegistryUtil.startWorkflowInstance(
2398 message.getCompanyId(), message.getGroupId(), userId,
2399 message.getWorkflowClassName(), message.getMessageId(), message,
2400 serviceContext, workflowContext);
2401 }
2402
2403 protected void updateAsset(
2404 long userId, MBMessage message, long[] assetCategoryIds,
2405 String[] assetTagNames, long[] assetLinkEntryIds,
2406 boolean assetEntryVisible)
2407 throws PortalException {
2408
2409 boolean visible = false;
2410
2411 if (assetEntryVisible && message.isApproved() &&
2412 ((message.getClassNameId() == 0) ||
2413 (message.getParentMessageId() != 0))) {
2414
2415 visible = true;
2416 }
2417
2418 AssetEntry assetEntry = assetEntryLocalService.updateEntry(
2419 userId, message.getGroupId(), message.getCreateDate(),
2420 message.getModifiedDate(), message.getWorkflowClassName(),
2421 message.getMessageId(), message.getUuid(), 0, assetCategoryIds,
2422 assetTagNames, visible, null, null, null, ContentTypes.TEXT_HTML,
2423 message.getSubject(), null, null, null, null, 0, 0,
2424 message.getPriority());
2425
2426 assetLinkLocalService.updateLinks(
2427 userId, assetEntry.getEntryId(), assetLinkEntryIds,
2428 AssetLinkConstants.TYPE_RELATED);
2429 }
2430
2431 protected void updatePriorities(long threadId, double priority) {
2432 List<MBMessage> messages = mbMessagePersistence.findByThreadId(
2433 threadId);
2434
2435 for (MBMessage message : messages) {
2436 if (message.getPriority() != priority) {
2437 message.setPriority(priority);
2438
2439 mbMessagePersistence.update(message);
2440 }
2441 }
2442 }
2443
2444 protected void updateThreadStatus(
2445 MBThread thread, MBMessage message, User user, int oldStatus,
2446 Date modifiedDate)
2447 throws PortalException {
2448
2449 MBCategory category = null;
2450
2451 int status = message.getStatus();
2452
2453 if ((thread.getCategoryId() !=
2454 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
2455 (thread.getCategoryId() !=
2456 MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
2457
2458 category = mbCategoryPersistence.findByPrimaryKey(
2459 thread.getCategoryId());
2460 }
2461
2462 if ((thread.getRootMessageId() == message.getMessageId()) &&
2463 (oldStatus != status)) {
2464
2465 thread.setModifiedDate(modifiedDate);
2466 thread.setStatus(status);
2467 thread.setStatusByUserId(user.getUserId());
2468 thread.setStatusByUserName(user.getFullName());
2469 thread.setStatusDate(modifiedDate);
2470 }
2471
2472 if (status == oldStatus) {
2473 return;
2474 }
2475
2476 if (status == WorkflowConstants.STATUS_APPROVED) {
2477 if (message.isAnonymous()) {
2478 thread.setLastPostByUserId(0);
2479 }
2480 else {
2481 thread.setLastPostByUserId(message.getUserId());
2482 }
2483
2484 thread.setLastPostDate(modifiedDate);
2485
2486 if (category != null) {
2487 category.setLastPostDate(modifiedDate);
2488
2489 category = mbCategoryPersistence.update(category);
2490 }
2491 }
2492
2493 if ((oldStatus == WorkflowConstants.STATUS_APPROVED) ||
2494 (status == WorkflowConstants.STATUS_APPROVED)) {
2495
2496
2497
2498 MBUtil.updateThreadMessageCount(thread.getThreadId());
2499
2500
2501
2502 if ((category != null) &&
2503 (thread.getRootMessageId() == message.getMessageId())) {
2504
2505 MBUtil.updateCategoryStatistics(category.getCategoryId());
2506 }
2507
2508 if ((category != null) &&
2509 !(thread.getRootMessageId() == message.getMessageId())) {
2510
2511 MBUtil.updateCategoryMessageCount(category.getCategoryId());
2512 }
2513 }
2514
2515
2516
2517 Indexer<MBThread> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
2518 MBThread.class);
2519
2520 indexer.reindex(thread);
2521
2522 mbThreadPersistence.update(thread);
2523 }
2524
2525 protected void validate(String subject, String body)
2526 throws PortalException {
2527
2528 if (Validator.isNull(subject) && Validator.isNull(body)) {
2529 throw new MessageSubjectException("Subject and body are null");
2530 }
2531 }
2532
2533 protected void validateDiscussionMaxComments(String className, long classPK)
2534 throws PortalException {
2535
2536 if (PropsValues.DISCUSSION_MAX_COMMENTS <= 0) {
2537 return;
2538 }
2539
2540 int count = getDiscussionMessagesCount(
2541 className, classPK, WorkflowConstants.STATUS_APPROVED);
2542
2543 if (count >= PropsValues.DISCUSSION_MAX_COMMENTS) {
2544 int max = PropsValues.DISCUSSION_MAX_COMMENTS - 1;
2545
2546 throw new DiscussionMaxCommentsException(count + " exceeds " + max);
2547 }
2548 }
2549
2550 private static final Log _log = LogFactoryUtil.getLog(
2551 MBMessageLocalServiceImpl.class);
2552
2553 }