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