001
014
015 package com.liferay.portlet.blogs.service.impl;
016
017 import com.liferay.portal.kernel.exception.PortalException;
018 import com.liferay.portal.kernel.exception.SystemException;
019 import com.liferay.portal.kernel.json.JSONFactoryUtil;
020 import com.liferay.portal.kernel.json.JSONObject;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.search.Indexer;
024 import com.liferay.portal.kernel.search.IndexerRegistryUtil;
025 import com.liferay.portal.kernel.util.Constants;
026 import com.liferay.portal.kernel.util.ContentTypes;
027 import com.liferay.portal.kernel.util.FileUtil;
028 import com.liferay.portal.kernel.util.GetterUtil;
029 import com.liferay.portal.kernel.util.HtmlUtil;
030 import com.liferay.portal.kernel.util.HttpUtil;
031 import com.liferay.portal.kernel.util.OrderByComparator;
032 import com.liferay.portal.kernel.util.PropsKeys;
033 import com.liferay.portal.kernel.util.SetUtil;
034 import com.liferay.portal.kernel.util.StringBundler;
035 import com.liferay.portal.kernel.util.StringPool;
036 import com.liferay.portal.kernel.util.StringUtil;
037 import com.liferay.portal.kernel.util.Validator;
038 import com.liferay.portal.kernel.workflow.WorkflowConstants;
039 import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
040 import com.liferay.portal.model.Group;
041 import com.liferay.portal.model.ResourceConstants;
042 import com.liferay.portal.model.User;
043 import com.liferay.portal.service.ServiceContext;
044 import com.liferay.portal.service.ServiceContextUtil;
045 import com.liferay.portal.util.Portal;
046 import com.liferay.portal.util.PortalUtil;
047 import com.liferay.portal.util.PortletKeys;
048 import com.liferay.portal.util.PrefsPropsUtil;
049 import com.liferay.portal.util.PropsValues;
050 import com.liferay.portal.util.SubscriptionSender;
051 import com.liferay.portlet.asset.model.AssetEntry;
052 import com.liferay.portlet.asset.model.AssetLinkConstants;
053 import com.liferay.portlet.blogs.EntryContentException;
054 import com.liferay.portlet.blogs.EntryDisplayDateException;
055 import com.liferay.portlet.blogs.EntrySmallImageNameException;
056 import com.liferay.portlet.blogs.EntrySmallImageSizeException;
057 import com.liferay.portlet.blogs.EntryTitleException;
058 import com.liferay.portlet.blogs.model.BlogsEntry;
059 import com.liferay.portlet.blogs.service.base.BlogsEntryLocalServiceBaseImpl;
060 import com.liferay.portlet.blogs.social.BlogsActivityKeys;
061 import com.liferay.portlet.blogs.util.BlogsUtil;
062 import com.liferay.portlet.blogs.util.LinkbackProducerUtil;
063 import com.liferay.portlet.blogs.util.comparator.EntryDisplayDateComparator;
064
065 import java.io.IOException;
066 import java.io.InputStream;
067
068 import java.util.Date;
069 import java.util.HashMap;
070 import java.util.HashSet;
071 import java.util.List;
072 import java.util.Locale;
073 import java.util.Map;
074 import java.util.Set;
075 import java.util.regex.Matcher;
076 import java.util.regex.Pattern;
077
078 import javax.portlet.PortletPreferences;
079
080 import net.htmlparser.jericho.Source;
081 import net.htmlparser.jericho.StartTag;
082
083
091 public class BlogsEntryLocalServiceImpl extends BlogsEntryLocalServiceBaseImpl {
092
093 public BlogsEntry addEntry(
094 long userId, String title, String description, String content,
095 int displayDateMonth, int displayDateDay, int displayDateYear,
096 int displayDateHour, int displayDateMinute, boolean allowPingbacks,
097 boolean allowTrackbacks, String[] trackbacks, boolean smallImage,
098 String smallImageURL, String smallImageFileName,
099 InputStream smallImageInputStream, ServiceContext serviceContext)
100 throws PortalException, SystemException {
101
102
103
104 User user = userPersistence.findByPrimaryKey(userId);
105 long groupId = serviceContext.getScopeGroupId();
106
107 Date displayDate = PortalUtil.getDate(
108 displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
109 displayDateMinute, user.getTimeZone(),
110 EntryDisplayDateException.class);
111
112 byte[] smallImageBytes = null;
113
114 try {
115 if ((smallImageInputStream != null) && smallImage) {
116 smallImageBytes = FileUtil.getBytes(smallImageInputStream);
117 }
118 }
119 catch (IOException ioe) {
120 }
121
122 Date now = new Date();
123
124 validate(
125 title, content, smallImage, smallImageURL, smallImageFileName,
126 smallImageBytes);
127
128 long entryId = counterLocalService.increment();
129
130 BlogsEntry entry = blogsEntryPersistence.create(entryId);
131
132 entry.setUuid(serviceContext.getUuid());
133 entry.setGroupId(groupId);
134 entry.setCompanyId(user.getCompanyId());
135 entry.setUserId(user.getUserId());
136 entry.setUserName(user.getFullName());
137 entry.setCreateDate(serviceContext.getCreateDate(now));
138 entry.setModifiedDate(serviceContext.getModifiedDate(now));
139 entry.setTitle(title);
140 entry.setUrlTitle(
141 getUniqueUrlTitle(entryId, title, null, serviceContext));
142 entry.setDescription(description);
143 entry.setContent(content);
144 entry.setDisplayDate(displayDate);
145 entry.setAllowPingbacks(allowPingbacks);
146 entry.setAllowTrackbacks(allowTrackbacks);
147 entry.setSmallImage(smallImage);
148 entry.setSmallImageId(counterLocalService.increment());
149 entry.setSmallImageURL(smallImageURL);
150 entry.setStatus(WorkflowConstants.STATUS_DRAFT);
151 entry.setStatusDate(serviceContext.getModifiedDate(now));
152 entry.setExpandoBridgeAttributes(serviceContext);
153
154 blogsEntryPersistence.update(entry, false);
155
156
157
158 if (serviceContext.isAddGroupPermissions() ||
159 serviceContext.isAddGuestPermissions()) {
160
161 addEntryResources(
162 entry, serviceContext.isAddGroupPermissions(),
163 serviceContext.isAddGuestPermissions());
164 }
165 else {
166 addEntryResources(
167 entry, serviceContext.getGroupPermissions(),
168 serviceContext.getGuestPermissions());
169 }
170
171
172
173 saveImages(smallImage, entry.getSmallImageId(), smallImageBytes);
174
175
176
177 updateAsset(
178 userId, entry, serviceContext.getAssetCategoryIds(),
179 serviceContext.getAssetTagNames(),
180 serviceContext.getAssetLinkEntryIds());
181
182
183
184 if (PropsValues.BLOGS_ENTRY_COMMENTS_ENABLED) {
185 mbMessageLocalService.addDiscussionMessage(
186 userId, entry.getUserName(), groupId,
187 BlogsEntry.class.getName(), entryId,
188 WorkflowConstants.ACTION_PUBLISH);
189 }
190
191
192
193 if ((trackbacks != null) && (trackbacks.length > 0)) {
194 serviceContext.setAttribute("trackbacks", trackbacks);
195 }
196 else {
197 serviceContext.setAttribute("trackbacks", null);
198 }
199
200 WorkflowHandlerRegistryUtil.startWorkflowInstance(
201 user.getCompanyId(), groupId, userId, BlogsEntry.class.getName(),
202 entry.getEntryId(), entry, serviceContext);
203
204 return entry;
205 }
206
207 public void addEntryResources(
208 BlogsEntry entry, boolean addGroupPermissions,
209 boolean addGuestPermissions)
210 throws PortalException, SystemException {
211
212 resourceLocalService.addResources(
213 entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
214 BlogsEntry.class.getName(), entry.getEntryId(), false,
215 addGroupPermissions, addGuestPermissions);
216 }
217
218 public void addEntryResources(
219 BlogsEntry entry, String[] groupPermissions,
220 String[] guestPermissions)
221 throws PortalException, SystemException {
222
223 resourceLocalService.addModelResources(
224 entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
225 BlogsEntry.class.getName(), entry.getEntryId(), groupPermissions,
226 guestPermissions);
227 }
228
229 public void addEntryResources(
230 long entryId, boolean addGroupPermissions,
231 boolean addGuestPermissions)
232 throws PortalException, SystemException {
233
234 BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
235
236 addEntryResources(entry, addGroupPermissions, addGuestPermissions);
237 }
238
239 public void addEntryResources(
240 long entryId, String[] groupPermissions, String[] guestPermissions)
241 throws PortalException, SystemException {
242
243 BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
244
245 addEntryResources(entry, groupPermissions, guestPermissions);
246 }
247
248 public void checkEntries() throws PortalException, SystemException {
249 Date now = new Date();
250
251 int count = blogsEntryPersistence.countByLtD_S(
252 now, WorkflowConstants.STATUS_SCHEDULED);
253
254 if (count == 0) {
255 return;
256 }
257
258 List<BlogsEntry> entries = blogsEntryPersistence.findByLtD_S(
259 now, WorkflowConstants.STATUS_SCHEDULED);
260
261 for (BlogsEntry entry : entries) {
262 ServiceContext serviceContext = new ServiceContext();
263
264 String[] trackbacks = StringUtil.split(entry.getTrackbacks());
265
266 serviceContext.setAttribute("trackbacks", trackbacks);
267
268 serviceContext.setCommand(Constants.UPDATE);
269
270 String layoutFullURL = PortalUtil.getLayoutFullURL(
271 entry.getGroupId(), PortletKeys.BLOGS);
272
273 serviceContext.setLayoutFullURL(layoutFullURL);
274
275 serviceContext.setScopeGroupId(entry.getGroupId());
276
277 updateStatus(
278 entry.getStatusByUserId(), entry.getEntryId(),
279 WorkflowConstants.STATUS_APPROVED, serviceContext);
280 }
281 }
282
283 public void deleteEntries(long groupId)
284 throws PortalException, SystemException {
285
286 for (BlogsEntry entry : blogsEntryPersistence.findByGroupId(groupId)) {
287 deleteEntry(entry);
288 }
289 }
290
291 public void deleteEntry(BlogsEntry entry)
292 throws PortalException, SystemException {
293
294
295
296 blogsEntryPersistence.remove(entry);
297
298
299
300 resourceLocalService.deleteResource(
301 entry.getCompanyId(), BlogsEntry.class.getName(),
302 ResourceConstants.SCOPE_INDIVIDUAL, entry.getEntryId());
303
304
305
306 imageLocalService.deleteImage(entry.getSmallImageId());
307
308
309
310 subscriptionLocalService.deleteSubscriptions(
311 entry.getCompanyId(), BlogsEntry.class.getName(),
312 entry.getEntryId());
313
314
315
316 blogsStatsUserLocalService.updateStatsUser(
317 entry.getGroupId(), entry.getUserId());
318
319
320
321 assetEntryLocalService.deleteEntry(
322 BlogsEntry.class.getName(), entry.getEntryId());
323
324
325
326 expandoValueLocalService.deleteValues(
327 BlogsEntry.class.getName(), entry.getEntryId());
328
329
330
331 mbMessageLocalService.deleteDiscussionMessages(
332 BlogsEntry.class.getName(), entry.getEntryId());
333
334
335
336 ratingsStatsLocalService.deleteStats(
337 BlogsEntry.class.getName(), entry.getEntryId());
338
339
340
341 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
342 BlogsEntry.class);
343
344 indexer.delete(entry);
345
346
347
348 workflowInstanceLinkLocalService.deleteWorkflowInstanceLinks(
349 entry.getCompanyId(), entry.getGroupId(),
350 BlogsEntry.class.getName(), entry.getEntryId());
351 }
352
353 public void deleteEntry(long entryId)
354 throws PortalException, SystemException {
355
356 BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
357
358 deleteEntry(entry);
359 }
360
361 public List<BlogsEntry> getCompanyEntries(
362 long companyId, Date displayDate, int status, int start, int end)
363 throws SystemException {
364
365 if (status == WorkflowConstants.STATUS_ANY) {
366 return blogsEntryPersistence.findByC_LtD(
367 companyId, displayDate, start, end);
368 }
369 else {
370 return blogsEntryPersistence.findByC_LtD_S(
371 companyId, displayDate, status, start, end);
372 }
373 }
374
375 public List<BlogsEntry> getCompanyEntries(
376 long companyId, Date displayDate, int status, int start, int end,
377 OrderByComparator obc)
378 throws SystemException {
379
380 if (status == WorkflowConstants.STATUS_ANY) {
381 return blogsEntryPersistence.findByC_LtD(
382 companyId, displayDate, start, end, obc);
383 }
384 else {
385 return blogsEntryPersistence.findByC_LtD_S(
386 companyId, displayDate, status, start, end, obc);
387 }
388 }
389
390 public int getCompanyEntriesCount(
391 long companyId, Date displayDate, int status)
392 throws SystemException {
393
394 if (status == WorkflowConstants.STATUS_ANY) {
395 return blogsEntryPersistence.countByC_LtD(companyId, displayDate);
396 }
397 else {
398 return blogsEntryPersistence.countByC_LtD_S(
399 companyId, displayDate, status);
400 }
401 }
402
403 public BlogsEntry[] getEntriesPrevAndNext(long entryId)
404 throws PortalException, SystemException {
405
406 BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
407
408 return blogsEntryPersistence.findByG_S_PrevAndNext(
409 entry.getEntryId(), entry.getGroupId(),
410 WorkflowConstants.STATUS_APPROVED,
411 new EntryDisplayDateComparator(true));
412 }
413
414 public BlogsEntry getEntry(long entryId)
415 throws PortalException, SystemException {
416
417 return blogsEntryPersistence.findByPrimaryKey(entryId);
418 }
419
420 public BlogsEntry getEntry(long groupId, String urlTitle)
421 throws PortalException, SystemException {
422
423 return blogsEntryPersistence.findByG_UT(groupId, urlTitle);
424 }
425
426 public List<BlogsEntry> getGroupEntries(
427 long groupId, Date displayDate, int status, int start, int end)
428 throws SystemException {
429
430 if (status == WorkflowConstants.STATUS_ANY) {
431 return blogsEntryPersistence.findByG_LtD(
432 groupId, displayDate, start, end);
433 }
434 else {
435 return blogsEntryPersistence.findByG_LtD_S(
436 groupId, displayDate, status, start, end);
437 }
438 }
439
440 public List<BlogsEntry> getGroupEntries(
441 long groupId, Date displayDate, int status, int start, int end,
442 OrderByComparator obc)
443 throws SystemException {
444
445 if (status == WorkflowConstants.STATUS_ANY) {
446 return blogsEntryPersistence.findByG_LtD(
447 groupId, displayDate, start, end, obc);
448 }
449 else {
450 return blogsEntryPersistence.findByG_LtD_S(
451 groupId, displayDate, status, start, end, obc);
452 }
453 }
454
455 public List<BlogsEntry> getGroupEntries(
456 long groupId, int status, int start, int end)
457 throws SystemException {
458
459 if (status == WorkflowConstants.STATUS_ANY) {
460 return blogsEntryPersistence.findByGroupId(groupId, start, end);
461 }
462 else {
463 return blogsEntryPersistence.findByG_S(groupId, status, start, end);
464 }
465 }
466
467 public List<BlogsEntry> getGroupEntries(
468 long groupId, int status, int start, int end, OrderByComparator obc)
469 throws SystemException {
470
471 if (status == WorkflowConstants.STATUS_ANY) {
472 return blogsEntryPersistence.findByGroupId(
473 groupId, start, end, obc);
474 }
475 else {
476 return blogsEntryPersistence.findByG_S(
477 groupId, status, start, end, obc);
478 }
479 }
480
481 public int getGroupEntriesCount(long groupId, Date displayDate, int status)
482 throws SystemException {
483
484 if (status == WorkflowConstants.STATUS_ANY) {
485 return blogsEntryPersistence.countByG_LtD(groupId, displayDate);
486 }
487 else {
488 return blogsEntryPersistence.countByG_LtD_S(
489 groupId, displayDate, status);
490 }
491 }
492
493 public int getGroupEntriesCount(long groupId, int status)
494 throws SystemException {
495
496 if (status == WorkflowConstants.STATUS_ANY) {
497 return blogsEntryPersistence.countByGroupId(groupId);
498 }
499 else {
500 return blogsEntryPersistence.countByG_S(groupId, status);
501 }
502 }
503
504 public List<BlogsEntry> getGroupsEntries(
505 long companyId, long groupId, Date displayDate, int status,
506 int start, int end)
507 throws SystemException {
508
509 return blogsEntryFinder.findByGroupIds(
510 companyId, groupId, displayDate, status, start, end);
511 }
512
513 public List<BlogsEntry> getGroupUserEntries(
514 long groupId, long userId, Date displayDate, int status, int start,
515 int end)
516 throws SystemException {
517
518 if (status == WorkflowConstants.STATUS_ANY) {
519 return blogsEntryPersistence.findByG_U_LtD(
520 groupId, userId, displayDate, start, end);
521 }
522 else {
523 return blogsEntryPersistence.findByG_U_LtD_S(
524 groupId, userId, displayDate, status, start, end);
525 }
526 }
527
528 public List<BlogsEntry> getGroupUserEntries(
529 long groupId, long userId, Date displayDate, int status, int start,
530 int end, OrderByComparator obc)
531 throws SystemException {
532
533 if (status == WorkflowConstants.STATUS_ANY) {
534 return blogsEntryPersistence.findByG_U_LtD(
535 groupId, userId, displayDate, start, end, obc);
536 }
537 else {
538 return blogsEntryPersistence.findByG_U_LtD_S(
539 groupId, userId, displayDate, status, start, end, obc);
540 }
541 }
542
543 public int getGroupUserEntriesCount(
544 long groupId, long userId, Date displayDate, int status)
545 throws SystemException {
546
547 if (status == WorkflowConstants.STATUS_ANY) {
548 return blogsEntryPersistence.countByG_U_LtD(
549 groupId, userId, displayDate);
550 }
551 else {
552 return blogsEntryPersistence.countByG_U_LtD_S(
553 groupId, userId, displayDate, status);
554 }
555 }
556
557 public List<BlogsEntry> getNoAssetEntries() throws SystemException {
558 return blogsEntryFinder.findByNoAssets();
559 }
560
561 public List<BlogsEntry> getOrganizationEntries(
562 long organizationId, Date displayDate, int status, int start,
563 int end)
564 throws SystemException {
565
566 return blogsEntryFinder.findByOrganizationId(
567 organizationId, displayDate, status, start, end, null);
568 }
569
570 public List<BlogsEntry> getOrganizationEntries(
571 long organizationId, Date displayDate, int status, int start,
572 int end, OrderByComparator obc)
573 throws SystemException {
574
575 return blogsEntryFinder.findByOrganizationId(
576 organizationId, displayDate, status, start, end, obc);
577 }
578
579 public int getOrganizationEntriesCount(
580 long organizationId, Date displayDate, int status)
581 throws SystemException {
582
583 return blogsEntryFinder.countByOrganizationId(
584 organizationId, displayDate, status);
585 }
586
587 public void subscribe(long userId, long groupId)
588 throws PortalException, SystemException {
589
590 subscriptionLocalService.addSubscription(
591 userId, groupId, BlogsEntry.class.getName(), groupId);
592 }
593
594 public void unsubscribe(long userId, long groupId)
595 throws PortalException, SystemException {
596
597 subscriptionLocalService.deleteSubscription(
598 userId, BlogsEntry.class.getName(), groupId);
599 }
600
601 public void updateAsset(
602 long userId, BlogsEntry entry, long[] assetCategoryIds,
603 String[] assetTagNames, long[] assetLinkEntryIds)
604 throws PortalException, SystemException {
605
606 boolean visible = false;
607
608 if (entry.isApproved()) {
609 visible = true;
610 }
611
612 String summary = HtmlUtil.extractText(
613 StringUtil.shorten(entry.getContent(), 500));
614
615 AssetEntry assetEntry = assetEntryLocalService.updateEntry(
616 userId, entry.getGroupId(), BlogsEntry.class.getName(),
617 entry.getEntryId(), entry.getUuid(), 0, assetCategoryIds,
618 assetTagNames, visible, null, null, entry.getDisplayDate(), null,
619 ContentTypes.TEXT_HTML, entry.getTitle(), null, summary, null, null,
620 0, 0, null, false);
621
622 assetLinkLocalService.updateLinks(
623 userId, assetEntry.getEntryId(), assetLinkEntryIds,
624 AssetLinkConstants.TYPE_RELATED);
625 }
626
627 public BlogsEntry updateEntry(
628 long userId, long entryId, String title, String description,
629 String content, int displayDateMonth, int displayDateDay,
630 int displayDateYear, int displayDateHour, int displayDateMinute,
631 boolean allowPingbacks, boolean allowTrackbacks,
632 String[] trackbacks, boolean smallImage, String smallImageURL,
633 String smallImageFileName, InputStream smallImageInputStream,
634 ServiceContext serviceContext)
635 throws PortalException, SystemException {
636
637
638
639 User user = userPersistence.findByPrimaryKey(userId);
640
641 Date displayDate = PortalUtil.getDate(
642 displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
643 displayDateMinute, user.getTimeZone(),
644 EntryDisplayDateException.class);
645
646 byte[] smallImageBytes = null;
647
648 try {
649 if ((smallImageInputStream != null) && smallImage) {
650 smallImageBytes = FileUtil.getBytes(smallImageInputStream);
651 }
652 }
653 catch (IOException ioe) {
654 }
655
656 validate(
657 title, content, smallImage, smallImageURL, smallImageFileName,
658 smallImageBytes);
659
660 BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
661
662 String oldUrlTitle = entry.getUrlTitle();
663
664 entry.setModifiedDate(serviceContext.getModifiedDate(null));
665 entry.setTitle(title);
666 entry.setUrlTitle(
667 getUniqueUrlTitle(entryId, title, oldUrlTitle, serviceContext));
668 entry.setDescription(description);
669 entry.setContent(content);
670 entry.setDisplayDate(displayDate);
671 entry.setAllowPingbacks(allowPingbacks);
672 entry.setAllowTrackbacks(allowTrackbacks);
673 entry.setSmallImage(smallImage);
674
675 if (entry.getSmallImageId() == 0) {
676 entry.setSmallImageId(counterLocalService.increment());
677 }
678
679 entry.setSmallImageURL(smallImageURL);
680
681 if (entry.isPending() || entry.isDraft()) {
682 }
683 else if (entry.isApproved()) {
684 entry.setStatus(WorkflowConstants.STATUS_DRAFT_FROM_APPROVED);
685 }
686 else {
687 entry.setStatus(WorkflowConstants.STATUS_DRAFT);
688 }
689
690 entry.setExpandoBridgeAttributes(serviceContext);
691
692 blogsEntryPersistence.update(entry, false);
693
694
695
696 if ((serviceContext.getGroupPermissions() != null) ||
697 (serviceContext.getGuestPermissions() != null)) {
698
699 updateEntryResources(
700 entry, serviceContext.getGroupPermissions(),
701 serviceContext.getGuestPermissions());
702 }
703
704
705
706 saveImages(smallImage, entry.getSmallImageId(), smallImageBytes);
707
708
709
710 updateAsset(
711 userId, entry, serviceContext.getAssetCategoryIds(),
712 serviceContext.getAssetTagNames(),
713 serviceContext.getAssetLinkEntryIds());
714
715
716
717 boolean pingOldTrackbacks = false;
718
719 if (!oldUrlTitle.equals(entry.getUrlTitle())) {
720 pingOldTrackbacks = true;
721 }
722
723 serviceContext.setAttribute(
724 "pingOldTrackbacks", String.valueOf(pingOldTrackbacks));
725
726 if (Validator.isNotNull(trackbacks)) {
727 serviceContext.setAttribute("trackbacks", trackbacks);
728 }
729 else {
730 serviceContext.setAttribute("trackbacks", null);
731 }
732
733 WorkflowHandlerRegistryUtil.startWorkflowInstance(
734 user.getCompanyId(), entry.getGroupId(), userId,
735 BlogsEntry.class.getName(), entry.getEntryId(), entry,
736 serviceContext);
737
738 return entry;
739 }
740
741 public void updateEntryResources(
742 BlogsEntry entry, String[] groupPermissions,
743 String[] guestPermissions)
744 throws PortalException, SystemException {
745
746 resourceLocalService.updateResources(
747 entry.getCompanyId(), entry.getGroupId(),
748 BlogsEntry.class.getName(), entry.getEntryId(), groupPermissions,
749 guestPermissions);
750 }
751
752 public BlogsEntry updateStatus(
753 long userId, long entryId, int status,
754 ServiceContext serviceContext)
755 throws PortalException, SystemException {
756
757
758
759 User user = userPersistence.findByPrimaryKey(userId);
760 Date now = new Date();
761
762 BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
763
764 int oldStatus = entry.getStatus();
765
766 if (oldStatus == WorkflowConstants.STATUS_DRAFT) {
767 serviceContext.setCommand(Constants.ADD);
768 }
769
770 if ((status == WorkflowConstants.STATUS_APPROVED) &&
771 now.before(entry.getDisplayDate())) {
772
773 status = WorkflowConstants.STATUS_SCHEDULED;
774 }
775
776 entry.setModifiedDate(serviceContext.getModifiedDate(now));
777 entry.setStatus(status);
778 entry.setStatusByUserId(user.getUserId());
779 entry.setStatusByUserName(user.getFullName());
780 entry.setStatusDate(serviceContext.getModifiedDate(now));
781
782 blogsEntryPersistence.update(entry, false);
783
784
785
786 blogsStatsUserLocalService.updateStatsUser(
787 entry.getGroupId(), user.getUserId(), entry.getDisplayDate());
788
789 Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
790 BlogsEntry.class);
791
792 JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
793
794 extraDataJSONObject.put("title", entry.getTitle());
795
796 if (status == WorkflowConstants.STATUS_APPROVED) {
797
798
799
800 assetEntryLocalService.updateVisible(
801 BlogsEntry.class.getName(), entryId, true);
802
803
804
805 if (oldStatus != WorkflowConstants.STATUS_SCHEDULED) {
806 if (serviceContext.isCommandUpdate()) {
807 socialActivityLocalService.addActivity(
808 user.getUserId(), entry.getGroupId(),
809 BlogsEntry.class.getName(), entryId,
810 BlogsActivityKeys.UPDATE_ENTRY,
811 extraDataJSONObject.toString(), 0);
812 }
813 else {
814 socialActivityLocalService.addUniqueActivity(
815 user.getUserId(), entry.getGroupId(),
816 BlogsEntry.class.getName(), entryId,
817 BlogsActivityKeys.ADD_ENTRY,
818 extraDataJSONObject.toString(), 0);
819 }
820 }
821
822
823
824 indexer.reindex(entry);
825
826
827
828 notifySubscribers(entry, serviceContext);
829
830
831
832 String[] trackbacks = (String[])serviceContext.getAttribute(
833 "trackbacks");
834 Boolean pingOldTrackbacks = GetterUtil.getBoolean(
835 (String)serviceContext.getAttribute("pingOldTrackbacks"));
836
837 pingGoogle(entry, serviceContext);
838 pingPingback(entry, serviceContext);
839 pingTrackbacks(
840 entry, trackbacks, pingOldTrackbacks, serviceContext);
841 }
842 else {
843
844
845
846 assetEntryLocalService.updateVisible(
847 BlogsEntry.class.getName(), entryId, false);
848
849
850
851 if (status == WorkflowConstants.STATUS_SCHEDULED) {
852 if (serviceContext.isCommandUpdate()) {
853 socialActivityLocalService.addActivity(
854 user.getUserId(), entry.getGroupId(),
855 BlogsEntry.class.getName(), entryId,
856 BlogsActivityKeys.UPDATE_ENTRY,
857 extraDataJSONObject.toString(), 0);
858 }
859 else {
860 socialActivityLocalService.addUniqueActivity(
861 user.getUserId(), entry.getGroupId(),
862 BlogsEntry.class.getName(), entryId,
863 BlogsActivityKeys.ADD_ENTRY,
864 extraDataJSONObject.toString(), 0);
865 }
866 }
867
868
869
870 indexer.delete(entry);
871 }
872
873 return entry;
874 }
875
876 protected String getUniqueUrlTitle(long entryId, long groupId, String title)
877 throws SystemException {
878
879 String urlTitle = BlogsUtil.getUrlTitle(entryId, title);
880
881 for (int i = 1;; i++) {
882 BlogsEntry entry = blogsEntryPersistence.fetchByG_UT(
883 groupId, urlTitle);
884
885 if ((entry == null) || (entryId == entry.getEntryId())) {
886 break;
887 }
888 else {
889 String suffix = StringPool.DASH + i;
890
891 String prefix = urlTitle;
892
893 if (urlTitle.length() > suffix.length()) {
894 prefix = urlTitle.substring(
895 0, urlTitle.length() - suffix.length());
896 }
897
898 urlTitle = prefix + suffix;
899 }
900 }
901
902 return urlTitle;
903 }
904
905 protected String getUniqueUrlTitle(
906 long entryId, String title, String oldUrlTitle,
907 ServiceContext serviceContext)
908 throws SystemException {
909
910 String serviceContextUrlTitle = GetterUtil.getString(
911 serviceContext.getAttribute("urlTitle"));
912
913 String urlTitle = null;
914
915 if (isMatchesServiceContextUrlTitle(serviceContextUrlTitle)) {
916 urlTitle = BlogsUtil.getUrlTitle(entryId, serviceContextUrlTitle);
917
918 BlogsEntry urlTitleEntry = blogsEntryPersistence.fetchByG_UT(
919 serviceContext.getScopeGroupId(), urlTitle);
920
921 if ((urlTitleEntry != null) &&
922 (urlTitleEntry.getEntryId() != entryId)) {
923
924 urlTitle = getUniqueUrlTitle(
925 entryId, serviceContext.getScopeGroupId(), urlTitle);
926 }
927 }
928 else {
929 if (isMatchesServiceContextUrlTitle(oldUrlTitle)) {
930 urlTitle = oldUrlTitle;
931 }
932 else {
933 urlTitle = getUniqueUrlTitle(
934 entryId, serviceContext.getScopeGroupId(), title);
935 }
936 }
937
938 return urlTitle;
939 }
940
941 protected boolean isMatchesServiceContextUrlTitle(String urlTitle) {
942 if (Validator.isNotNull(urlTitle) &&
943 Validator.isNotNull(PropsValues.BLOGS_ENTRY_URL_TITLE_REGEXP)) {
944
945 Pattern pattern = Pattern.compile(
946 PropsValues.BLOGS_ENTRY_URL_TITLE_REGEXP);
947
948 Matcher matcher = pattern.matcher(urlTitle);
949
950 return matcher.matches();
951 }
952
953 return false;
954 }
955
956 protected void notifySubscribers(
957 BlogsEntry entry, ServiceContext serviceContext)
958 throws SystemException {
959
960 if (!entry.isApproved()) {
961 return;
962 }
963
964 String layoutFullURL = serviceContext.getLayoutFullURL();
965
966 if (Validator.isNull(layoutFullURL)) {
967 return;
968 }
969
970 PortletPreferences preferences =
971 ServiceContextUtil.getPortletPreferences(serviceContext);
972
973 if (preferences == null) {
974 long ownerId = entry.getGroupId();
975 int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
976 long plid = PortletKeys.PREFS_PLID_SHARED;
977 String portletId = PortletKeys.BLOGS;
978 String defaultPreferences = null;
979
980 preferences = portletPreferencesLocalService.getPreferences(
981 entry.getCompanyId(), ownerId, ownerType, plid, portletId,
982 defaultPreferences);
983 }
984
985 if (serviceContext.isCommandAdd() &&
986 BlogsUtil.getEmailEntryAddedEnabled(preferences)) {
987 }
988 else if (serviceContext.isCommandUpdate() &&
989 BlogsUtil.getEmailEntryUpdatedEnabled(preferences)) {
990 }
991 else {
992 return;
993 }
994
995 String entryURL =
996 layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs" +
997 StringPool.SLASH + entry.getEntryId();
998
999 String fromName = BlogsUtil.getEmailFromName(
1000 preferences, entry.getCompanyId());
1001 String fromAddress = BlogsUtil.getEmailFromAddress(
1002 preferences, entry.getCompanyId());
1003
1004 Map<Locale, String> localizedSubjectMap = null;
1005 Map<Locale, String> localizedBodyMap = null;
1006
1007 if (serviceContext.isCommandUpdate()) {
1008 localizedSubjectMap = BlogsUtil.getEmailEntryUpdatedSubjectMap(
1009 preferences);
1010 localizedBodyMap = BlogsUtil.getEmailEntryUpdatedBodyMap(
1011 preferences);
1012 }
1013 else {
1014 localizedSubjectMap = BlogsUtil.getEmailEntryAddedSubjectMap(
1015 preferences);
1016 localizedBodyMap = BlogsUtil.getEmailEntryAddedBodyMap(preferences);
1017 }
1018
1019 SubscriptionSender subscriptionSender = new SubscriptionSender();
1020
1021 subscriptionSender.setCompanyId(entry.getCompanyId());
1022 subscriptionSender.setContextAttributes(
1023 "[$BLOGS_ENTRY_STATUS_BY_USER_NAME$]", entry.getStatusByUserName(),
1024 "[$BLOGS_ENTRY_URL$]", entryURL);
1025 subscriptionSender.setContextUserPrefix("BLOGS_ENTRY");
1026 subscriptionSender.setFrom(fromAddress, fromName);
1027 subscriptionSender.setHtmlFormat(true);
1028 subscriptionSender.setLocalizedBodyMap(localizedBodyMap);
1029 subscriptionSender.setLocalizedSubjectMap(localizedSubjectMap);
1030 subscriptionSender.setMailId("blogs_entry", entry.getEntryId());
1031 subscriptionSender.setPortletId(PortletKeys.BLOGS);
1032 subscriptionSender.setReplyToAddress(fromAddress);
1033 subscriptionSender.setScopeGroupId(entry.getGroupId());
1034 subscriptionSender.setServiceContext(serviceContext);
1035 subscriptionSender.setUserId(entry.getUserId());
1036
1037 subscriptionSender.addPersistedSubscribers(
1038 BlogsEntry.class.getName(), entry.getGroupId());
1039
1040 subscriptionSender.flushNotificationsAsync();
1041 }
1042
1043 protected void pingGoogle(BlogsEntry entry, ServiceContext serviceContext)
1044 throws PortalException, SystemException {
1045
1046 if (!PropsValues.BLOGS_PING_GOOGLE_ENABLED || !entry.isApproved()) {
1047 return;
1048 }
1049
1050 String layoutFullURL = PortalUtil.getLayoutFullURL(
1051 serviceContext.getScopeGroupId(), PortletKeys.BLOGS);
1052
1053 if (Validator.isNull(layoutFullURL)) {
1054 return;
1055 }
1056
1057 if (layoutFullURL.contains(":
1058 if (_log.isDebugEnabled()) {
1059 _log.debug(
1060 "Not pinging Google because of localhost URL " +
1061 layoutFullURL);
1062 }
1063
1064 return;
1065 }
1066
1067 Group group = groupPersistence.findByPrimaryKey(entry.getGroupId());
1068
1069 StringBundler sb = new StringBundler(6);
1070
1071 String name = group.getDescriptiveName();
1072 String url = layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs";
1073 String changesURL =
1074 layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/rss";
1075
1076 sb.append("http:
1077 sb.append(HttpUtil.encodeURL(name));
1078 sb.append("&url=");
1079 sb.append(HttpUtil.encodeURL(url));
1080 sb.append("&changesURL=");
1081 sb.append(HttpUtil.encodeURL(changesURL));
1082
1083 String location = sb.toString();
1084
1085 if (_log.isInfoEnabled()) {
1086 _log.info("Pinging Google at " + location);
1087 }
1088
1089 try {
1090 String response = HttpUtil.URLtoString(sb.toString());
1091
1092 if (_log.isInfoEnabled()) {
1093 _log.info("Google ping response: " + response);
1094 }
1095 }
1096 catch (IOException ioe) {
1097 _log.error("Unable to ping Google at " + location, ioe);
1098 }
1099 }
1100
1101 protected void pingPingback(
1102 BlogsEntry entry, ServiceContext serviceContext) {
1103
1104 if (!PropsValues.BLOGS_PINGBACK_ENABLED ||
1105 !entry.isAllowPingbacks() || !entry.isApproved()) {
1106
1107 return;
1108 }
1109
1110 String layoutFullURL = serviceContext.getLayoutFullURL();
1111
1112 if (Validator.isNull(layoutFullURL)) {
1113 return;
1114 }
1115
1116 String sourceUri =
1117 layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/" +
1118 entry.getUrlTitle();
1119
1120 Source source = new Source(entry.getContent());
1121
1122 List<StartTag> tags = source.getAllStartTags("a");
1123
1124 for (StartTag tag : tags) {
1125 String targetUri = tag.getAttributeValue("href");
1126
1127 if (Validator.isNotNull(targetUri)) {
1128 try {
1129 LinkbackProducerUtil.sendPingback(sourceUri, targetUri);
1130 }
1131 catch (Exception e) {
1132 _log.error("Error while sending pingback " + targetUri, e);
1133 }
1134 }
1135 }
1136 }
1137
1138 protected void pingTrackbacks(
1139 BlogsEntry entry, String[] trackbacks, boolean pingOldTrackbacks,
1140 ServiceContext serviceContext)
1141 throws SystemException {
1142
1143 if (!PropsValues.BLOGS_TRACKBACK_ENABLED ||
1144 !entry.isAllowTrackbacks() || !entry.isApproved()) {
1145
1146 return;
1147 }
1148
1149 String layoutFullURL = serviceContext.getLayoutFullURL();
1150
1151 if (Validator.isNull(layoutFullURL)) {
1152 return;
1153 }
1154
1155 Map<String, String> parts = new HashMap<String, String>();
1156
1157 String excerpt = StringUtil.shorten(
1158 HtmlUtil.extractText(entry.getContent()),
1159 PropsValues.BLOGS_LINKBACK_EXCERPT_LENGTH);
1160 String url =
1161 layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/" +
1162 entry.getUrlTitle();
1163
1164 parts.put("title", entry.getTitle());
1165 parts.put("excerpt", excerpt);
1166 parts.put("url", url);
1167 parts.put("blog_name", entry.getUserName());
1168
1169 Set<String> trackbacksSet = null;
1170
1171 if (Validator.isNotNull(trackbacks)) {
1172 trackbacksSet = SetUtil.fromArray(trackbacks);
1173 }
1174 else {
1175 trackbacksSet = new HashSet<String>();
1176 }
1177
1178 if (pingOldTrackbacks) {
1179 trackbacksSet.addAll(
1180 SetUtil.fromArray(StringUtil.split(entry.getTrackbacks())));
1181
1182 entry.setTrackbacks(StringPool.BLANK);
1183
1184 blogsEntryPersistence.update(entry, false);
1185 }
1186
1187 Set<String> oldTrackbacks = SetUtil.fromArray(
1188 StringUtil.split(entry.getTrackbacks()));
1189
1190 Set<String> validTrackbacks = new HashSet<String>();
1191
1192 for (String trackback : trackbacksSet) {
1193 if (oldTrackbacks.contains(trackback)) {
1194 continue;
1195 }
1196
1197 try {
1198 if (LinkbackProducerUtil.sendTrackback(trackback, parts)) {
1199 validTrackbacks.add(trackback);
1200 }
1201 }
1202 catch (Exception e) {
1203 _log.error("Error while sending trackback at " + trackback, e);
1204 }
1205 }
1206
1207 if (!validTrackbacks.isEmpty()) {
1208 String newTrackbacks = StringUtil.merge(validTrackbacks);
1209
1210 if (Validator.isNotNull(entry.getTrackbacks())) {
1211 newTrackbacks += StringPool.COMMA + entry.getTrackbacks();
1212 }
1213
1214 entry.setTrackbacks(newTrackbacks);
1215
1216 blogsEntryPersistence.update(entry, false);
1217 }
1218 }
1219
1220 protected void saveImages(
1221 boolean smallImage, long smallImageId, byte[] smallImageBytes)
1222 throws PortalException, SystemException {
1223
1224 if (smallImage) {
1225 if (smallImageBytes != null) {
1226 imageLocalService.updateImage(smallImageId, smallImageBytes);
1227 }
1228 }
1229 else {
1230 imageLocalService.deleteImage(smallImageId);
1231 }
1232 }
1233
1234 protected void validate(
1235 String title, String content, boolean smallImage,
1236 String smallImageURL, String smallImageFileName,
1237 byte[] smallImageBytes)
1238 throws PortalException, SystemException {
1239
1240 if (Validator.isNull(title)) {
1241 throw new EntryTitleException();
1242 }
1243 else if (Validator.isNull(content)) {
1244 throw new EntryContentException();
1245 }
1246
1247 String[] imageExtensions = PrefsPropsUtil.getStringArray(
1248 PropsKeys.BLOGS_IMAGE_EXTENSIONS, StringPool.COMMA);
1249
1250 if (smallImage && Validator.isNull(smallImageURL) &&
1251 (smallImageBytes != null)) {
1252
1253 if (smallImageFileName != null) {
1254 boolean validSmallImageExtension = false;
1255
1256 for (String _imageExtension : imageExtensions) {
1257 if (StringPool.STAR.equals(_imageExtension) ||
1258 StringUtil.endsWith(
1259 smallImageFileName, _imageExtension)) {
1260
1261 validSmallImageExtension = true;
1262
1263 break;
1264 }
1265 }
1266
1267 if (!validSmallImageExtension) {
1268 throw new EntrySmallImageNameException(smallImageFileName);
1269 }
1270 }
1271
1272 long smallImageMaxSize = PrefsPropsUtil.getLong(
1273 PropsKeys.BLOGS_IMAGE_SMALL_MAX_SIZE);
1274
1275 if ((smallImageMaxSize > 0) &&
1276 ((smallImageBytes == null) ||
1277 (smallImageBytes.length > smallImageMaxSize))) {
1278
1279 throw new EntrySmallImageSizeException();
1280 }
1281 }
1282 }
1283
1284 private static Log _log = LogFactoryUtil.getLog(
1285 BlogsEntryLocalServiceImpl.class);
1286
1287 }