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.MBGroupServiceSettings;
078 import com.liferay.portlet.messageboards.constants.MBConstants;
079 import com.liferay.portlet.messageboards.exception.DiscussionMaxCommentsException;
080 import com.liferay.portlet.messageboards.exception.MessageBodyException;
081 import com.liferay.portlet.messageboards.exception.MessageSubjectException;
082 import com.liferay.portlet.messageboards.exception.NoSuchThreadException;
083 import com.liferay.portlet.messageboards.exception.RequiredMessageException;
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, boolean includePrevAndNext)
1176 throws PortalException {
1177
1178 MBMessage message = getMessage(messageId);
1179
1180 return getMessageDisplay(userId, message, status, includePrevAndNext);
1181 }
1182
1183
1187 @Deprecated
1188 @Override
1189 public MBMessageDisplay getMessageDisplay(
1190 long userId, long messageId, int status, String threadView,
1191 boolean includePrevAndNext)
1192 throws PortalException {
1193
1194 MBMessage message = getMessage(messageId);
1195
1196 return getMessageDisplay(
1197 userId, message, status, threadView, includePrevAndNext);
1198 }
1199
1200 @Override
1201 public MBMessageDisplay getMessageDisplay(
1202 long userId, MBMessage message, int status,
1203 boolean includePrevAndNext)
1204 throws PortalException {
1205
1206 return getMessageDisplay(
1207 userId, message, status, includePrevAndNext,
1208 new MessageThreadComparator());
1209 }
1210
1211 @Override
1212 public MBMessageDisplay getMessageDisplay(
1213 long userId, MBMessage message, int status,
1214 boolean includePrevAndNext, Comparator<MBMessage> comparator)
1215 throws PortalException {
1216
1217 MBCategory category = null;
1218
1219 if ((message.getCategoryId() !=
1220 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
1221 (message.getCategoryId() !=
1222 MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
1223
1224 category = mbCategoryPersistence.findByPrimaryKey(
1225 message.getCategoryId());
1226 }
1227 else {
1228 category = new MBCategoryImpl();
1229
1230 category.setCategoryId(message.getCategoryId());
1231 category.setDisplayStyle(MBCategoryConstants.DEFAULT_DISPLAY_STYLE);
1232 }
1233
1234 MBMessage parentMessage = null;
1235
1236 if (message.isReply()) {
1237 parentMessage = mbMessagePersistence.findByPrimaryKey(
1238 message.getParentMessageId());
1239 }
1240
1241 MBThread thread = mbThreadPersistence.findByPrimaryKey(
1242 message.getThreadId());
1243
1244 if (message.isApproved() && !message.isDiscussion()) {
1245 mbThreadLocalService.incrementViewCounter(thread.getThreadId(), 1);
1246
1247 SocialActivityManagerUtil.addActivity(
1248 userId, thread, SocialActivityConstants.TYPE_VIEW,
1249 StringPool.BLANK, 0);
1250 }
1251
1252 MBThread previousThread = null;
1253 MBThread nextThread = null;
1254
1255 if (message.isApproved() && includePrevAndNext) {
1256 ThreadLastPostDateComparator threadLastPostDateComparator =
1257 new ThreadLastPostDateComparator(false);
1258
1259 MBThread[] prevAndNextThreads = null;
1260
1261 if (status == WorkflowConstants.STATUS_ANY) {
1262 prevAndNextThreads =
1263 mbThreadPersistence.filterFindByG_C_NotS_PrevAndNext(
1264 message.getThreadId(), message.getGroupId(),
1265 message.getCategoryId(),
1266 WorkflowConstants.STATUS_IN_TRASH,
1267 threadLastPostDateComparator);
1268 }
1269 else {
1270 prevAndNextThreads =
1271 mbThreadPersistence.filterFindByG_C_S_PrevAndNext(
1272 message.getThreadId(), message.getGroupId(),
1273 message.getCategoryId(), status,
1274 threadLastPostDateComparator);
1275 }
1276
1277 previousThread = prevAndNextThreads[0];
1278 nextThread = prevAndNextThreads[2];
1279 }
1280
1281 return new MBMessageDisplayImpl(
1282 message, parentMessage, category, thread, previousThread,
1283 nextThread, status, this, comparator);
1284 }
1285
1286
1290 @Deprecated
1291 @Override
1292 public MBMessageDisplay getMessageDisplay(
1293 long userId, MBMessage message, int status, String threadView,
1294 boolean includePrevAndNext)
1295 throws PortalException {
1296
1297 return getMessageDisplay(
1298 userId, message, status, threadView, includePrevAndNext,
1299 new MessageThreadComparator());
1300 }
1301
1302
1306 @Deprecated
1307 @Override
1308 public MBMessageDisplay getMessageDisplay(
1309 long userId, MBMessage message, int status, String threadView,
1310 boolean includePrevAndNext, Comparator<MBMessage> comparator)
1311 throws PortalException {
1312
1313 MBMessageDisplay messageDisplay = getMessageDisplay(
1314 userId, message, status, includePrevAndNext, comparator);
1315
1316 return new MBMessageDisplayImpl(
1317 messageDisplay.getMessage(), messageDisplay.getParentMessage(),
1318 messageDisplay.getCategory(), messageDisplay.getThread(),
1319 messageDisplay.getPreviousThread(), messageDisplay.getNextThread(),
1320 status, threadView, this, comparator);
1321 }
1322
1323 @Override
1324 public List<MBMessage> getMessages(
1325 String className, long classPK, int status) {
1326
1327 long classNameId = classNameLocalService.getClassNameId(className);
1328
1329 if (status == WorkflowConstants.STATUS_ANY) {
1330 return mbMessagePersistence.findByC_C(classNameId, classPK);
1331 }
1332 else {
1333 return mbMessagePersistence.findByC_C_S(
1334 classNameId, classPK, status);
1335 }
1336 }
1337
1338 @Override
1339 public List<MBMessage> getNoAssetMessages() {
1340 return mbMessageFinder.findByNoAssets();
1341 }
1342
1343 @Override
1344 public int getPositionInThread(long messageId) throws PortalException {
1345 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1346
1347 return mbMessageFinder.countByC_T(
1348 message.getCreateDate(), message.getThreadId());
1349 }
1350
1351 @Override
1352 public List<MBMessage> getThreadMessages(long threadId, int status) {
1353 return getThreadMessages(
1354 threadId, status, new MessageThreadComparator());
1355 }
1356
1357 @Override
1358 public List<MBMessage> getThreadMessages(
1359 long threadId, int status, Comparator<MBMessage> comparator) {
1360
1361 List<MBMessage> messages = null;
1362
1363 if (status == WorkflowConstants.STATUS_ANY) {
1364 messages = mbMessagePersistence.findByThreadId(threadId);
1365 }
1366 else {
1367 messages = mbMessagePersistence.findByT_S(threadId, status);
1368 }
1369
1370 return ListUtil.sort(messages, comparator);
1371 }
1372
1373 @Override
1374 public List<MBMessage> getThreadMessages(
1375 long threadId, int status, int start, int end) {
1376
1377 if (status == WorkflowConstants.STATUS_ANY) {
1378 return mbMessagePersistence.findByThreadId(threadId, start, end);
1379 }
1380 else {
1381 return mbMessagePersistence.findByT_S(threadId, status, start, end);
1382 }
1383 }
1384
1385 @Override
1386 public int getThreadMessagesCount(long threadId, int status) {
1387 if (status == WorkflowConstants.STATUS_ANY) {
1388 return mbMessagePersistence.countByThreadId(threadId);
1389 }
1390 else {
1391 return mbMessagePersistence.countByT_S(threadId, status);
1392 }
1393 }
1394
1395 @Override
1396 public List<MBMessage> getThreadRepliesMessages(
1397 long threadId, int status, int start, int end) {
1398
1399 if (status == WorkflowConstants.STATUS_ANY) {
1400 return mbMessagePersistence.findByThreadReplies(
1401 threadId, start, end);
1402 }
1403 else {
1404 return mbMessagePersistence.findByTR_S(
1405 threadId, status, start, end);
1406 }
1407 }
1408
1409 @Override
1410 public List<MBMessage> getUserDiscussionMessages(
1411 long userId, long classNameId, long classPK, int status, int start,
1412 int end, OrderByComparator<MBMessage> obc) {
1413
1414 if (status == WorkflowConstants.STATUS_ANY) {
1415 return mbMessagePersistence.findByU_C_C(
1416 userId, classNameId, classPK, start, end, obc);
1417 }
1418 else {
1419 return mbMessagePersistence.findByU_C_C_S(
1420 userId, classNameId, classPK, status, start, end, obc);
1421 }
1422 }
1423
1424 @Override
1425 public List<MBMessage> getUserDiscussionMessages(
1426 long userId, long[] classNameIds, int status, int start, int end,
1427 OrderByComparator<MBMessage> obc) {
1428
1429 if (status == WorkflowConstants.STATUS_ANY) {
1430 return mbMessagePersistence.findByU_C(
1431 userId, classNameIds, start, end, obc);
1432 }
1433 else {
1434 return mbMessagePersistence.findByU_C_S(
1435 userId, classNameIds, status, start, end, obc);
1436 }
1437 }
1438
1439 @Override
1440 public List<MBMessage> getUserDiscussionMessages(
1441 long userId, String className, long classPK, int status, int start,
1442 int end, OrderByComparator<MBMessage> obc) {
1443
1444 long classNameId = classNameLocalService.getClassNameId(className);
1445
1446 return getUserDiscussionMessages(
1447 userId, classNameId, classPK, status, start, end, obc);
1448 }
1449
1450 @Override
1451 public int getUserDiscussionMessagesCount(
1452 long userId, long classNameId, long classPK, int status) {
1453
1454 if (status == WorkflowConstants.STATUS_ANY) {
1455 return mbMessagePersistence.countByU_C_C(
1456 userId, classNameId, classPK);
1457 }
1458 else {
1459 return mbMessagePersistence.countByU_C_C_S(
1460 userId, classNameId, classPK, status);
1461 }
1462 }
1463
1464 @Override
1465 public int getUserDiscussionMessagesCount(
1466 long userId, long[] classNameIds, int status) {
1467
1468 if (status == WorkflowConstants.STATUS_ANY) {
1469 return mbMessagePersistence.countByU_C(userId, classNameIds);
1470 }
1471 else {
1472 return mbMessagePersistence.countByU_C_S(
1473 userId, classNameIds, status);
1474 }
1475 }
1476
1477 @Override
1478 public int getUserDiscussionMessagesCount(
1479 long userId, String className, long classPK, int status) {
1480
1481 long classNameId = classNameLocalService.getClassNameId(className);
1482
1483 return getUserDiscussionMessagesCount(
1484 userId, classNameId, classPK, status);
1485 }
1486
1487 @Override
1488 public long moveMessageAttachmentToTrash(
1489 long userId, long messageId, String fileName)
1490 throws PortalException {
1491
1492 MBMessage message = getMessage(messageId);
1493
1494 long folderId = message.getAttachmentsFolderId();
1495
1496 FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
1497 message.getGroupId(), folderId, fileName);
1498
1499 PortletFileRepositoryUtil.movePortletFileEntryToTrash(
1500 userId, fileEntry.getFileEntryId());
1501
1502 return fileEntry.getFileEntryId();
1503 }
1504
1505 @Override
1506 public void restoreMessageAttachmentFromTrash(
1507 long userId, long messageId, String deletedFileName)
1508 throws PortalException {
1509
1510 MBMessage message = getMessage(messageId);
1511
1512 Folder folder = message.addAttachmentsFolder();
1513
1514 PortletFileRepositoryUtil.restorePortletFileEntryFromTrash(
1515 message.getGroupId(), userId, folder.getFolderId(),
1516 deletedFileName);
1517 }
1518
1519 @Override
1520 public void subscribeMessage(long userId, long messageId)
1521 throws PortalException {
1522
1523 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1524
1525 subscriptionLocalService.addSubscription(
1526 userId, message.getGroupId(), MBThread.class.getName(),
1527 message.getThreadId());
1528 }
1529
1530 @Override
1531 public void unsubscribeMessage(long userId, long messageId)
1532 throws PortalException {
1533
1534 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1535
1536 subscriptionLocalService.deleteSubscription(
1537 userId, MBThread.class.getName(), message.getThreadId());
1538 }
1539
1540 @Override
1541 public void updateAnswer(long messageId, boolean answer, boolean cascade)
1542 throws PortalException {
1543
1544 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1545
1546 updateAnswer(message, answer, cascade);
1547 }
1548
1549 @Override
1550 public void updateAnswer(MBMessage message, boolean answer, boolean cascade)
1551 throws PortalException {
1552
1553 if (message.isAnswer() != answer) {
1554 message.setAnswer(answer);
1555
1556 mbMessagePersistence.update(message);
1557 }
1558
1559 if (cascade) {
1560 List<MBMessage> messages = mbMessagePersistence.findByT_P(
1561 message.getThreadId(), message.getMessageId());
1562
1563 for (MBMessage curMessage : messages) {
1564 updateAnswer(curMessage, answer, cascade);
1565 }
1566 }
1567 }
1568
1569 @Override
1570 public void updateAsset(
1571 long userId, MBMessage message, long[] assetCategoryIds,
1572 String[] assetTagNames, long[] assetLinkEntryIds)
1573 throws PortalException {
1574
1575 updateAsset(
1576 userId, message, assetCategoryIds, assetTagNames, assetLinkEntryIds,
1577 true);
1578 }
1579
1580 @Override
1581 public MBMessage updateDiscussionMessage(
1582 long userId, long messageId, String className, long classPK,
1583 String subject, String body, ServiceContext serviceContext)
1584 throws PortalException {
1585
1586 if (Validator.isNull(subject)) {
1587 if (Validator.isNotNull(body)) {
1588 int pos = Math.min(body.length(), 50);
1589
1590 subject = body.substring(0, pos) + "...";
1591 }
1592 else {
1593 throw new MessageBodyException("Body is null");
1594 }
1595 }
1596
1597 List<ObjectValuePair<String, InputStream>> inputStreamOVPs = null;
1598 List<String> existingFiles = null;
1599 double priority = 0.0;
1600 boolean allowPingbacks = false;
1601
1602 serviceContext.setAttribute("className", className);
1603 serviceContext.setAttribute("classPK", String.valueOf(classPK));
1604
1605 return updateMessage(
1606 userId, messageId, subject, body, inputStreamOVPs, existingFiles,
1607 priority, allowPingbacks, serviceContext);
1608 }
1609
1610 @Override
1611 public MBMessage updateMessage(
1612 long userId, long messageId, String body,
1613 ServiceContext serviceContext)
1614 throws PortalException {
1615
1616 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1617
1618 return updateMessage(
1619 userId, messageId, message.getSubject(), body, null, null,
1620 message.getPriority(), message.isAllowPingbacks(), serviceContext);
1621 }
1622
1623 @Override
1624 public MBMessage updateMessage(
1625 long userId, long messageId, String subject, String body,
1626 List<ObjectValuePair<String, InputStream>> inputStreamOVPs,
1627 List<String> existingFiles, double priority, boolean allowPingbacks,
1628 ServiceContext serviceContext)
1629 throws PortalException {
1630
1631
1632
1633 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1634
1635 int oldStatus = message.getStatus();
1636
1637 Date modifiedDate = serviceContext.getModifiedDate(null);
1638 subject = ModelHintsUtil.trimString(
1639 MBMessage.class.getName(), "subject", subject);
1640
1641 Map<String, Object> options = new HashMap<>();
1642
1643 options.put("discussion", message.isDiscussion());
1644
1645 body = SanitizerUtil.sanitize(
1646 message.getCompanyId(), message.getGroupId(), userId,
1647 MBMessage.class.getName(), messageId, "text/" + message.getFormat(),
1648 Sanitizer.MODE_ALL, body, options);
1649
1650 validate(subject, body);
1651
1652 subject = getSubject(subject, body);
1653 body = getBody(subject, body);
1654
1655 message.setModifiedDate(modifiedDate);
1656 message.setSubject(subject);
1657 message.setBody(body);
1658 message.setAllowPingbacks(allowPingbacks);
1659
1660 if (priority != MBThreadConstants.PRIORITY_NOT_GIVEN) {
1661 message.setPriority(priority);
1662 }
1663
1664 MBThread thread = mbThreadPersistence.findByPrimaryKey(
1665 message.getThreadId());
1666
1667 if (serviceContext.getWorkflowAction() ==
1668 WorkflowConstants.ACTION_SAVE_DRAFT) {
1669
1670 if (!message.isDraft() && !message.isPending()) {
1671 message.setStatus(WorkflowConstants.STATUS_DRAFT);
1672
1673
1674
1675 User user = userPersistence.findByPrimaryKey(userId);
1676
1677 updateThreadStatus(
1678 thread, message, user, oldStatus, modifiedDate);
1679
1680
1681
1682 assetEntryLocalService.updateVisible(
1683 message.getWorkflowClassName(), message.getMessageId(),
1684 false);
1685
1686 if (!message.isDiscussion()) {
1687
1688
1689
1690 Indexer<MBMessage> indexer =
1691 IndexerRegistryUtil.nullSafeGetIndexer(MBMessage.class);
1692
1693 indexer.delete(message);
1694 }
1695 }
1696 }
1697
1698
1699
1700 if ((inputStreamOVPs != null) || (existingFiles != null)) {
1701 if (ListUtil.isNotEmpty(inputStreamOVPs) ||
1702 ListUtil.isNotEmpty(existingFiles)) {
1703
1704 List<FileEntry> fileEntries =
1705 message.getAttachmentsFileEntries();
1706
1707 for (FileEntry fileEntry : fileEntries) {
1708 String fileEntryId = String.valueOf(
1709 fileEntry.getFileEntryId());
1710
1711 if (!existingFiles.contains(fileEntryId)) {
1712 if (!TrashUtil.isTrashEnabled(message.getGroupId())) {
1713 deleteMessageAttachment(
1714 messageId, fileEntry.getTitle());
1715 }
1716 else {
1717 moveMessageAttachmentToTrash(
1718 userId, messageId, fileEntry.getTitle());
1719 }
1720 }
1721 }
1722
1723 Folder folder = message.addAttachmentsFolder();
1724
1725 PortletFileRepositoryUtil.addPortletFileEntries(
1726 message.getGroupId(), userId, MBMessage.class.getName(),
1727 message.getMessageId(), MBConstants.SERVICE_NAME,
1728 folder.getFolderId(), inputStreamOVPs);
1729 }
1730 else {
1731 if (TrashUtil.isTrashEnabled(message.getGroupId())) {
1732 List<FileEntry> fileEntries =
1733 message.getAttachmentsFileEntries();
1734
1735 for (FileEntry fileEntry : fileEntries) {
1736 moveMessageAttachmentToTrash(
1737 userId, messageId, fileEntry.getTitle());
1738 }
1739 }
1740 else {
1741 deleteMessageAttachments(message.getMessageId());
1742 }
1743 }
1744 }
1745
1746 message.setExpandoBridgeAttributes(serviceContext);
1747
1748 mbMessagePersistence.update(message);
1749
1750
1751
1752 if ((serviceContext.getWorkflowAction() ==
1753 WorkflowConstants.ACTION_SAVE_DRAFT) &&
1754 !message.isDiscussion()) {
1755
1756 mbStatsUserLocalService.updateStatsUser(
1757 message.getGroupId(), userId, message.getModifiedDate());
1758 }
1759
1760
1761
1762 if ((priority != MBThreadConstants.PRIORITY_NOT_GIVEN) &&
1763 (thread.getPriority() != priority)) {
1764
1765 thread.setPriority(priority);
1766
1767 mbThreadPersistence.update(thread);
1768
1769 updatePriorities(thread.getThreadId(), priority);
1770 }
1771
1772
1773
1774 updateAsset(
1775 userId, message, serviceContext.getAssetCategoryIds(),
1776 serviceContext.getAssetTagNames(),
1777 serviceContext.getAssetLinkEntryIds());
1778
1779
1780
1781 startWorkflowInstance(userId, message, serviceContext);
1782
1783 return message;
1784 }
1785
1786
1789 @Deprecated
1790 @Override
1791 public MBMessage updateMessage(long messageId, String body)
1792 throws PortalException {
1793
1794 MBMessage message = mbMessagePersistence.findByPrimaryKey(messageId);
1795
1796 message.setBody(body);
1797
1798 mbMessagePersistence.update(message);
1799
1800 return message;
1801 }
1802
1803
1807 @Deprecated
1808 @Override
1809 public MBMessage updateStatus(
1810 long userId, long messageId, int status,
1811 ServiceContext serviceContext)
1812 throws PortalException {
1813
1814 return updateStatus(
1815 userId, messageId, status, serviceContext,
1816 new HashMap<String, Serializable>());
1817 }
1818
1819 @Override
1820 public MBMessage updateStatus(
1821 long userId, long messageId, int status,
1822 ServiceContext serviceContext,
1823 Map<String, Serializable> workflowContext)
1824 throws PortalException {
1825
1826
1827
1828 MBMessage message = getMessage(messageId);
1829
1830 int oldStatus = message.getStatus();
1831
1832 User user = userPersistence.findByPrimaryKey(userId);
1833 Date now = new Date();
1834
1835 Date modifiedDate = serviceContext.getModifiedDate(now);
1836
1837 message.setStatus(status);
1838 message.setStatusByUserId(userId);
1839 message.setStatusByUserName(user.getFullName());
1840 message.setStatusDate(modifiedDate);
1841
1842 mbMessagePersistence.update(message);
1843
1844
1845
1846 MBThread thread = mbThreadPersistence.findByPrimaryKey(
1847 message.getThreadId());
1848
1849 updateThreadStatus(thread, message, user, oldStatus, modifiedDate);
1850
1851 Indexer<MBMessage> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1852 MBMessage.class);
1853
1854 if (status == WorkflowConstants.STATUS_APPROVED) {
1855 if (oldStatus != WorkflowConstants.STATUS_APPROVED) {
1856
1857
1858
1859 if (serviceContext.isAssetEntryVisible() &&
1860 ((message.getClassNameId() == 0) ||
1861 (message.getParentMessageId() != 0))) {
1862
1863 Date publishDate = null;
1864
1865 AssetEntry assetEntry = assetEntryLocalService.fetchEntry(
1866 message.getWorkflowClassName(), message.getMessageId());
1867
1868 if ((assetEntry != null) &&
1869 (assetEntry.getPublishDate() != null)) {
1870
1871 publishDate = assetEntry.getPublishDate();
1872 }
1873 else {
1874 publishDate = now;
1875
1876 serviceContext.setCommand(Constants.ADD);
1877 }
1878
1879 assetEntryLocalService.updateEntry(
1880 message.getWorkflowClassName(), message.getMessageId(),
1881 publishDate, true);
1882 }
1883
1884 if (serviceContext.isCommandAdd()) {
1885
1886
1887
1888 JSONObject extraDataJSONObject =
1889 JSONFactoryUtil.createJSONObject();
1890
1891 extraDataJSONObject.put("title", message.getSubject());
1892
1893 if (!message.isDiscussion() ) {
1894 if (!message.isAnonymous() && !user.isDefaultUser()) {
1895 long receiverUserId = 0;
1896
1897 MBMessage parentMessage =
1898 mbMessagePersistence.fetchByPrimaryKey(
1899 message.getParentMessageId());
1900
1901 if (parentMessage != null) {
1902 receiverUserId = parentMessage.getUserId();
1903 }
1904
1905 SocialActivityManagerUtil.addActivity(
1906 message.getUserId(), message,
1907 MBActivityKeys.ADD_MESSAGE,
1908 extraDataJSONObject.toString(), receiverUserId);
1909
1910 if ((parentMessage != null) &&
1911 (receiverUserId != message.getUserId())) {
1912
1913 SocialActivityManagerUtil.addActivity(
1914 message.getUserId(), parentMessage,
1915 MBActivityKeys.REPLY_MESSAGE,
1916 extraDataJSONObject.toString(), 0);
1917 }
1918 }
1919 }
1920 else {
1921 String className = (String)serviceContext.getAttribute(
1922 "className");
1923 long classPK = ParamUtil.getLong(
1924 serviceContext, "classPK");
1925 long parentMessageId = message.getParentMessageId();
1926
1927 if (parentMessageId !=
1928 MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID) {
1929
1930 AssetEntry assetEntry =
1931 assetEntryLocalService.fetchEntry(
1932 className, classPK);
1933
1934 if (assetEntry != null) {
1935 extraDataJSONObject.put(
1936 "messageId", message.getMessageId());
1937
1938 SocialActivityManagerUtil.addActivity(
1939 message.getUserId(), assetEntry,
1940 SocialActivityConstants.TYPE_ADD_COMMENT,
1941 extraDataJSONObject.toString(),
1942 assetEntry.getUserId());
1943 }
1944 }
1945 }
1946 }
1947 }
1948
1949
1950
1951 notifySubscribers(
1952 userId, (MBMessage)message.clone(),
1953 (String)workflowContext.get(WorkflowConstants.CONTEXT_URL),
1954 serviceContext);
1955
1956
1957
1958 indexer.reindex(message);
1959
1960
1961
1962 pingPingback(message, serviceContext);
1963 }
1964 else if (oldStatus == WorkflowConstants.STATUS_APPROVED) {
1965
1966
1967
1968 assetEntryLocalService.updateVisible(
1969 message.getWorkflowClassName(), message.getMessageId(), false);
1970
1971
1972
1973 indexer.delete(message);
1974 }
1975
1976
1977
1978 if (!message.isDiscussion()) {
1979 mbStatsUserLocalService.updateStatsUser(
1980 message.getGroupId(), userId,
1981 serviceContext.getModifiedDate(now));
1982 }
1983
1984 return message;
1985 }
1986
1987 @Override
1988 public void updateUserName(long userId, String userName) {
1989 List<MBMessage> messages = mbMessagePersistence.findByUserId(userId);
1990
1991 for (MBMessage message : messages) {
1992 message.setUserName(userName);
1993
1994 mbMessagePersistence.update(message);
1995 }
1996 }
1997
1998 protected String getBody(String subject, String body) {
1999 if (Validator.isNull(body)) {
2000 return subject;
2001 }
2002
2003 return body;
2004 }
2005
2006 protected String getMessageURL(
2007 MBMessage message, ServiceContext serviceContext)
2008 throws PortalException {
2009
2010 String entryURL = GetterUtil.getString(
2011 serviceContext.getAttribute("entryURL"));
2012
2013 if (Validator.isNotNull(entryURL)) {
2014 return entryURL;
2015 }
2016
2017 HttpServletRequest request = serviceContext.getRequest();
2018
2019 if (request == null) {
2020 if (Validator.isNull(serviceContext.getLayoutFullURL())) {
2021 return StringPool.BLANK;
2022 }
2023
2024 return serviceContext.getLayoutFullURL() +
2025 Portal.FRIENDLY_URL_SEPARATOR + "message_boards/view_message/" +
2026 message.getMessageId();
2027 }
2028
2029 String portletId = PortletProviderUtil.getPortletId(
2030 MBMessage.class.getName(), PortletProvider.Action.VIEW);
2031
2032 String layoutURL = LayoutURLUtil.getLayoutURL(
2033 message.getGroupId(), portletId, serviceContext);
2034
2035 if (Validator.isNotNull(layoutURL)) {
2036 return layoutURL + Portal.FRIENDLY_URL_SEPARATOR +
2037 "message_boards/view_message/" + message.getMessageId();
2038 }
2039 else {
2040 portletId = PortletProviderUtil.getPortletId(
2041 MBMessage.class.getName(), PortletProvider.Action.MANAGE);
2042
2043 PortletURL portletURL = PortalUtil.getControlPanelPortletURL(
2044 request, portletId, PortletRequest.RENDER_PHASE);
2045
2046 portletURL.setParameter(
2047 "mvcRenderCommandName", "/message_boards/view_message");
2048 portletURL.setParameter(
2049 "messageId", String.valueOf(message.getMessageId()));
2050
2051 return portletURL.toString();
2052 }
2053 }
2054
2055 protected String getSubject(String subject, String body) {
2056 if (Validator.isNull(subject)) {
2057 return StringUtil.shorten(body);
2058 }
2059
2060 return subject;
2061 }
2062
2063 protected MBSubscriptionSender getSubscriptionSender(
2064 long userId, MBMessage message, String messageURL, String entryTitle,
2065 boolean htmlFormat, String messageBody, String categoryName,
2066 String inReplyTo, String fromName, String fromAddress,
2067 String replyToAddress, String emailAddress, String fullName,
2068 LocalizedValuesMap subjectLocalizedValuesMap,
2069 LocalizedValuesMap bodyLocalizedValuesMap,
2070 ServiceContext serviceContext) {
2071
2072 MBSubscriptionSender subscriptionSender = new MBSubscriptionSender(
2073 MBPermission.RESOURCE_NAME);
2074
2075 subscriptionSender.setBulk(PropsValues.MESSAGE_BOARDS_EMAIL_BULK);
2076 subscriptionSender.setClassName(message.getModelClassName());
2077 subscriptionSender.setClassPK(message.getMessageId());
2078 subscriptionSender.setCompanyId(message.getCompanyId());
2079 subscriptionSender.setContextAttribute(
2080 "[$MESSAGE_BODY$]", messageBody, false);
2081 subscriptionSender.setContextAttributes(
2082 "[$CATEGORY_NAME$]", categoryName, "[$MAILING_LIST_ADDRESS$]",
2083 replyToAddress, "[$MESSAGE_ID$]", message.getMessageId(),
2084 "[$MESSAGE_SUBJECT$]", entryTitle, "[$MESSAGE_URL$]", messageURL,
2085 "[$MESSAGE_USER_ADDRESS$]", emailAddress, "[$MESSAGE_USER_NAME$]",
2086 fullName);
2087 subscriptionSender.setCurrentUserId(userId);
2088 subscriptionSender.setEntryTitle(entryTitle);
2089 subscriptionSender.setEntryURL(messageURL);
2090 subscriptionSender.setFrom(fromAddress, fromName);
2091 subscriptionSender.setHtmlFormat(htmlFormat);
2092 subscriptionSender.setInReplyTo(inReplyTo);
2093
2094 if (bodyLocalizedValuesMap != null) {
2095 subscriptionSender.setLocalizedBodyMap(
2096 LocalizationUtil.getMap(bodyLocalizedValuesMap));
2097 }
2098
2099 if (subjectLocalizedValuesMap != null) {
2100 subscriptionSender.setLocalizedSubjectMap(
2101 LocalizationUtil.getMap(subjectLocalizedValuesMap));
2102 }
2103
2104 Date modifiedDate = message.getModifiedDate();
2105
2106 subscriptionSender.setMailId(
2107 MBUtil.MESSAGE_POP_PORTLET_PREFIX, message.getCategoryId(),
2108 message.getMessageId(), modifiedDate.getTime());
2109
2110 int notificationType =
2111 UserNotificationDefinition.NOTIFICATION_TYPE_ADD_ENTRY;
2112
2113 if (serviceContext.isCommandUpdate()) {
2114 notificationType =
2115 UserNotificationDefinition.NOTIFICATION_TYPE_UPDATE_ENTRY;
2116 }
2117
2118 subscriptionSender.setNotificationType(notificationType);
2119
2120 String portletId = PortletProviderUtil.getPortletId(
2121 MBMessage.class.getName(), PortletProvider.Action.VIEW);
2122
2123 subscriptionSender.setPortletId(portletId);
2124
2125 subscriptionSender.setReplyToAddress(replyToAddress);
2126 subscriptionSender.setScopeGroupId(message.getGroupId());
2127 subscriptionSender.setServiceContext(serviceContext);
2128 subscriptionSender.setUniqueMailId(false);
2129
2130 return subscriptionSender;
2131 }
2132
2133 protected void notifyDiscussionSubscribers(
2134 long userId, MBMessage message, ServiceContext serviceContext)
2135 throws PortalException {
2136
2137 if (!PrefsPropsUtil.getBoolean(
2138 message.getCompanyId(),
2139 PropsKeys.DISCUSSION_EMAIL_COMMENTS_ADDED_ENABLED)) {
2140
2141 return;
2142 }
2143
2144 MBDiscussion mbDiscussion =
2145 mbDiscussionLocalService.getThreadDiscussion(message.getThreadId());
2146
2147 String contentURL = (String)serviceContext.getAttribute("contentURL");
2148
2149 String userAddress = StringPool.BLANK;
2150 String userName = (String)serviceContext.getAttribute(
2151 "pingbackUserName");
2152
2153 if (Validator.isNull(userName)) {
2154 userAddress = PortalUtil.getUserEmailAddress(message.getUserId());
2155 userName = PortalUtil.getUserName(
2156 message.getUserId(), StringPool.BLANK);
2157 }
2158
2159 String fromName = PrefsPropsUtil.getString(
2160 message.getCompanyId(), PropsKeys.ADMIN_EMAIL_FROM_NAME);
2161 String fromAddress = PrefsPropsUtil.getString(
2162 message.getCompanyId(), PropsKeys.ADMIN_EMAIL_FROM_ADDRESS);
2163
2164 String subject = PrefsPropsUtil.getContent(
2165 message.getCompanyId(), PropsKeys.DISCUSSION_EMAIL_SUBJECT);
2166 String body = PrefsPropsUtil.getContent(
2167 message.getCompanyId(), PropsKeys.DISCUSSION_EMAIL_BODY);
2168
2169 SubscriptionSender subscriptionSender = new SubscriptionSender();
2170
2171 subscriptionSender.setBody(body);
2172 subscriptionSender.setCompanyId(message.getCompanyId());
2173 subscriptionSender.setClassName(MBDiscussion.class.getName());
2174 subscriptionSender.setClassPK(mbDiscussion.getDiscussionId());
2175 subscriptionSender.setContextAttribute(
2176 "[$COMMENTS_BODY$]", message.getBody(true), false);
2177 subscriptionSender.setContextAttributes(
2178 "[$COMMENTS_USER_ADDRESS$]", userAddress, "[$COMMENTS_USER_NAME$]",
2179 userName, "[$CONTENT_URL$]", contentURL);
2180 subscriptionSender.setCurrentUserId(userId);
2181 subscriptionSender.setEntryTitle(message.getBody());
2182 subscriptionSender.setEntryURL(contentURL);
2183 subscriptionSender.setFrom(fromAddress, fromName);
2184 subscriptionSender.setHtmlFormat(true);
2185
2186 Date modifiedDate = message.getModifiedDate();
2187
2188 subscriptionSender.setMailId(
2189 "mb_discussion", message.getCategoryId(), message.getMessageId(),
2190 modifiedDate.getTime());
2191
2192 int notificationType =
2193 UserNotificationDefinition.NOTIFICATION_TYPE_ADD_ENTRY;
2194
2195 if (serviceContext.isCommandUpdate()) {
2196 notificationType =
2197 UserNotificationDefinition.NOTIFICATION_TYPE_UPDATE_ENTRY;
2198 }
2199
2200 subscriptionSender.setNotificationType(notificationType);
2201
2202 String portletId = PortletProviderUtil.getPortletId(
2203 Comment.class.getName(), PortletProvider.Action.VIEW);
2204
2205 subscriptionSender.setPortletId(portletId);
2206
2207 subscriptionSender.setScopeGroupId(message.getGroupId());
2208 subscriptionSender.setServiceContext(serviceContext);
2209 subscriptionSender.setSubject(subject);
2210 subscriptionSender.setUniqueMailId(false);
2211
2212 String className = (String)serviceContext.getAttribute("className");
2213 long classPK = ParamUtil.getLong(serviceContext, "classPK");
2214
2215 subscriptionSender.addPersistedSubscribers(className, classPK);
2216
2217 subscriptionSender.flushNotificationsAsync();
2218 }
2219
2220 protected void notifySubscribers(
2221 long userId, MBMessage message, String messageURL,
2222 ServiceContext serviceContext)
2223 throws PortalException {
2224
2225 if (!message.isApproved() || Validator.isNull(messageURL)) {
2226 return;
2227 }
2228
2229 if (message.isDiscussion()) {
2230 try {
2231 notifyDiscussionSubscribers(userId, message, serviceContext);
2232 }
2233 catch (Exception e) {
2234 _log.error(e, e);
2235 }
2236
2237 return;
2238 }
2239
2240 MBGroupServiceSettings mbGroupServiceSettings =
2241 MBGroupServiceSettings.getInstance(message.getGroupId());
2242
2243 if (serviceContext.isCommandAdd() &&
2244 mbGroupServiceSettings.isEmailMessageAddedEnabled()) {
2245 }
2246 else if (serviceContext.isCommandUpdate() &&
2247 mbGroupServiceSettings.isEmailMessageUpdatedEnabled()) {
2248 }
2249 else {
2250 return;
2251 }
2252
2253 Company company = companyPersistence.findByPrimaryKey(
2254 message.getCompanyId());
2255
2256 Group group = groupPersistence.findByPrimaryKey(message.getGroupId());
2257
2258 String emailAddress = PortalUtil.getUserEmailAddress(
2259 message.getUserId());
2260 String fullName = PortalUtil.getUserName(
2261 message.getUserId(), message.getUserName());
2262
2263 if (message.isAnonymous()) {
2264 emailAddress = StringPool.BLANK;
2265 fullName = serviceContext.translate("anonymous");
2266 }
2267
2268 MBCategory category = message.getCategory();
2269
2270 String categoryName = category.getName();
2271
2272 if (category.getCategoryId() ==
2273 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
2274
2275 categoryName = serviceContext.translate("message-boards-home");
2276
2277 categoryName += " - " + group.getDescriptiveName();
2278 }
2279
2280 List<Long> categoryIds = new ArrayList<>();
2281
2282 categoryIds.add(message.getCategoryId());
2283
2284 if (message.getCategoryId() !=
2285 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
2286
2287 categoryIds.addAll(category.getAncestorCategoryIds());
2288 }
2289
2290 String entryTitle = message.getSubject();
2291
2292 String fromName = mbGroupServiceSettings.getEmailFromName();
2293 String fromAddress = mbGroupServiceSettings.getEmailFromAddress();
2294
2295 String replyToAddress = StringPool.BLANK;
2296
2297 if (PropsValues.POP_SERVER_NOTIFICATIONS_ENABLED) {
2298 replyToAddress = MBUtil.getReplyToAddress(
2299 message.getCategoryId(), message.getMessageId(),
2300 company.getMx(), fromAddress);
2301 }
2302
2303 LocalizedValuesMap subjectLocalizedValuesMap = null;
2304 LocalizedValuesMap bodyLocalizedValuesMap = null;
2305
2306 if (serviceContext.isCommandUpdate()) {
2307 subjectLocalizedValuesMap =
2308 mbGroupServiceSettings.getEmailMessageUpdatedSubject();
2309 bodyLocalizedValuesMap =
2310 mbGroupServiceSettings.getEmailMessageUpdatedBody();
2311 }
2312 else {
2313 subjectLocalizedValuesMap =
2314 mbGroupServiceSettings.getEmailMessageAddedSubject();
2315 bodyLocalizedValuesMap =
2316 mbGroupServiceSettings.getEmailMessageAddedBody();
2317 }
2318
2319 boolean htmlFormat = mbGroupServiceSettings.isEmailHtmlFormat();
2320
2321 String messageBody = message.getBody();
2322
2323 if (htmlFormat && message.isFormatBBCode()) {
2324 try {
2325 messageBody = BBCodeTranslatorUtil.getHTML(messageBody);
2326
2327 HttpServletRequest request = serviceContext.getRequest();
2328
2329 if (request != null) {
2330 ThemeDisplay themeDisplay =
2331 (ThemeDisplay)request.getAttribute(
2332 WebKeys.THEME_DISPLAY);
2333
2334 messageBody = MBUtil.replaceMessageBodyPaths(
2335 themeDisplay, messageBody);
2336 }
2337 }
2338 catch (Exception e) {
2339 _log.error(
2340 "Could not parse message " + message.getMessageId() +
2341 " " + e.getMessage());
2342 }
2343 }
2344
2345 String inReplyTo = null;
2346
2347 if (message.getParentMessageId() !=
2348 MBMessageConstants.DEFAULT_PARENT_MESSAGE_ID) {
2349
2350 MBMessage parentMessage = mbMessageLocalService.getMessage(
2351 message.getParentMessageId());
2352
2353 Date modifiedDate = parentMessage.getModifiedDate();
2354
2355 inReplyTo = PortalUtil.getMailId(
2356 company.getMx(), MBUtil.MESSAGE_POP_PORTLET_PREFIX,
2357 message.getCategoryId(), parentMessage.getMessageId(),
2358 modifiedDate.getTime());
2359 }
2360
2361 SubscriptionSender subscriptionSender = getSubscriptionSender(
2362 userId, message, messageURL, entryTitle, htmlFormat, messageBody,
2363 categoryName, inReplyTo, fromName, fromAddress, replyToAddress,
2364 emailAddress, fullName, subjectLocalizedValuesMap,
2365 bodyLocalizedValuesMap, serviceContext);
2366
2367 subscriptionSender.addPersistedSubscribers(
2368 MBCategory.class.getName(), message.getGroupId());
2369
2370 for (long categoryId : categoryIds) {
2371 if (categoryId != MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
2372 subscriptionSender.addPersistedSubscribers(
2373 MBCategory.class.getName(), categoryId);
2374 }
2375 }
2376
2377 subscriptionSender.addPersistedSubscribers(
2378 MBThread.class.getName(), message.getThreadId());
2379
2380 subscriptionSender.flushNotificationsAsync();
2381
2382 if (!MailingListThreadLocal.isSourceMailingList()) {
2383 for (long categoryId : categoryIds) {
2384 MBSubscriptionSender sourceMailingListSubscriptionSender =
2385 getSubscriptionSender(
2386 userId, message, messageURL, entryTitle, htmlFormat,
2387 messageBody, categoryName, inReplyTo, fromName,
2388 fromAddress, replyToAddress, emailAddress, fullName,
2389 subjectLocalizedValuesMap, bodyLocalizedValuesMap,
2390 serviceContext);
2391
2392 sourceMailingListSubscriptionSender.setBulk(false);
2393
2394 sourceMailingListSubscriptionSender.addMailingListSubscriber(
2395 message.getGroupId(), categoryId);
2396
2397 sourceMailingListSubscriptionSender.flushNotificationsAsync();
2398 }
2399 }
2400 }
2401
2402 protected void pingPingback(
2403 MBMessage message, ServiceContext serviceContext) {
2404
2405 if (!PropsValues.BLOGS_PINGBACK_ENABLED ||
2406 !message.isAllowPingbacks() || !message.isApproved()) {
2407
2408 return;
2409 }
2410
2411 String layoutFullURL = serviceContext.getLayoutFullURL();
2412
2413 if (Validator.isNull(layoutFullURL)) {
2414 return;
2415 }
2416
2417 String sourceUri =
2418 layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR +
2419 "message_boards/view_message/" + message.getMessageId();
2420
2421 Source source = new Source(message.getBody(true));
2422
2423 List<StartTag> startTags = source.getAllStartTags("a");
2424
2425 for (StartTag startTag : startTags) {
2426 String targetUri = startTag.getAttributeValue("href");
2427
2428 if (Validator.isNotNull(targetUri)) {
2429 try {
2430 LinkbackProducerUtil.sendPingback(sourceUri, targetUri);
2431 }
2432 catch (Exception e) {
2433 _log.error("Error while sending pingback " + targetUri, e);
2434 }
2435 }
2436 }
2437 }
2438
2439 protected void startWorkflowInstance(
2440 long userId, MBMessage message, ServiceContext serviceContext)
2441 throws PortalException {
2442
2443 Map<String, Serializable> workflowContext = new HashMap<>();
2444
2445 workflowContext.put(
2446 WorkflowConstants.CONTEXT_URL,
2447 getMessageURL(message, serviceContext));
2448
2449 WorkflowHandlerRegistryUtil.startWorkflowInstance(
2450 message.getCompanyId(), message.getGroupId(), userId,
2451 message.getWorkflowClassName(), message.getMessageId(), message,
2452 serviceContext, workflowContext);
2453 }
2454
2455 protected void updateAsset(
2456 long userId, MBMessage message, long[] assetCategoryIds,
2457 String[] assetTagNames, long[] assetLinkEntryIds,
2458 boolean assetEntryVisible)
2459 throws PortalException {
2460
2461 boolean visible = false;
2462
2463 if (assetEntryVisible && message.isApproved() &&
2464 ((message.getClassNameId() == 0) ||
2465 (message.getParentMessageId() != 0))) {
2466
2467 visible = true;
2468 }
2469
2470 AssetEntry assetEntry = assetEntryLocalService.updateEntry(
2471 userId, message.getGroupId(), message.getCreateDate(),
2472 message.getModifiedDate(), message.getWorkflowClassName(),
2473 message.getMessageId(), message.getUuid(), 0, assetCategoryIds,
2474 assetTagNames, visible, null, null, null, ContentTypes.TEXT_HTML,
2475 message.getSubject(), null, null, null, null, 0, 0,
2476 message.getPriority());
2477
2478 assetLinkLocalService.updateLinks(
2479 userId, assetEntry.getEntryId(), assetLinkEntryIds,
2480 AssetLinkConstants.TYPE_RELATED);
2481 }
2482
2483 protected void updatePriorities(long threadId, double priority) {
2484 List<MBMessage> messages = mbMessagePersistence.findByThreadId(
2485 threadId);
2486
2487 for (MBMessage message : messages) {
2488 if (message.getPriority() != priority) {
2489 message.setPriority(priority);
2490
2491 mbMessagePersistence.update(message);
2492 }
2493 }
2494 }
2495
2496 protected void updateThreadStatus(
2497 MBThread thread, MBMessage message, User user, int oldStatus,
2498 Date modifiedDate)
2499 throws PortalException {
2500
2501 MBCategory category = null;
2502
2503 int status = message.getStatus();
2504
2505 if ((thread.getCategoryId() !=
2506 MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) &&
2507 (thread.getCategoryId() !=
2508 MBCategoryConstants.DISCUSSION_CATEGORY_ID)) {
2509
2510 category = mbCategoryPersistence.findByPrimaryKey(
2511 thread.getCategoryId());
2512 }
2513
2514 if ((thread.getRootMessageId() == message.getMessageId()) &&
2515 (oldStatus != status)) {
2516
2517 thread.setModifiedDate(modifiedDate);
2518 thread.setStatus(status);
2519 thread.setStatusByUserId(user.getUserId());
2520 thread.setStatusByUserName(user.getFullName());
2521 thread.setStatusDate(modifiedDate);
2522 }
2523
2524 if (status == oldStatus) {
2525 return;
2526 }
2527
2528 if (status == WorkflowConstants.STATUS_APPROVED) {
2529 if (message.isAnonymous()) {
2530 thread.setLastPostByUserId(0);
2531 }
2532 else {
2533 thread.setLastPostByUserId(message.getUserId());
2534 }
2535
2536 thread.setLastPostDate(modifiedDate);
2537
2538 if (category != null) {
2539 category.setLastPostDate(modifiedDate);
2540
2541 category = mbCategoryPersistence.update(category);
2542 }
2543 }
2544
2545 if ((oldStatus == WorkflowConstants.STATUS_APPROVED) ||
2546 (status == WorkflowConstants.STATUS_APPROVED)) {
2547
2548
2549
2550 MBUtil.updateThreadMessageCount(thread.getThreadId());
2551
2552
2553
2554 if ((category != null) &&
2555 (thread.getRootMessageId() == message.getMessageId())) {
2556
2557 MBUtil.updateCategoryStatistics(category.getCategoryId());
2558 }
2559
2560 if ((category != null) &&
2561 !(thread.getRootMessageId() == message.getMessageId())) {
2562
2563 MBUtil.updateCategoryMessageCount(category.getCategoryId());
2564 }
2565 }
2566
2567
2568
2569 Indexer<MBThread> indexer = IndexerRegistryUtil.nullSafeGetIndexer(
2570 MBThread.class);
2571
2572 indexer.reindex(thread);
2573
2574 mbThreadPersistence.update(thread);
2575 }
2576
2577 protected void validate(String subject, String body)
2578 throws PortalException {
2579
2580 if (Validator.isNull(subject) && Validator.isNull(body)) {
2581 throw new MessageSubjectException("Subject and body are null");
2582 }
2583 }
2584
2585 protected void validateDiscussionMaxComments(String className, long classPK)
2586 throws PortalException {
2587
2588 if (PropsValues.DISCUSSION_MAX_COMMENTS <= 0) {
2589 return;
2590 }
2591
2592 int count = getDiscussionMessagesCount(
2593 className, classPK, WorkflowConstants.STATUS_APPROVED);
2594
2595 if (count >= PropsValues.DISCUSSION_MAX_COMMENTS) {
2596 int max = PropsValues.DISCUSSION_MAX_COMMENTS - 1;
2597
2598 throw new DiscussionMaxCommentsException(count + " exceeds " + max);
2599 }
2600 }
2601
2602 private static final Log _log = LogFactoryUtil.getLog(
2603 MBMessageLocalServiceImpl.class);
2604
2605 }