001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.blogs.service.impl;
016    
017    import com.liferay.portal.kernel.dao.orm.QueryDefinition;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.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.search.Indexer;
025    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
026    import com.liferay.portal.kernel.util.Constants;
027    import com.liferay.portal.kernel.util.ContentTypes;
028    import com.liferay.portal.kernel.util.FileUtil;
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.ParamUtil;
033    import com.liferay.portal.kernel.util.PropsKeys;
034    import com.liferay.portal.kernel.util.SetUtil;
035    import com.liferay.portal.kernel.util.StringBundler;
036    import com.liferay.portal.kernel.util.StringPool;
037    import com.liferay.portal.kernel.util.StringUtil;
038    import com.liferay.portal.kernel.util.Validator;
039    import com.liferay.portal.kernel.util.WebKeys;
040    import com.liferay.portal.kernel.workflow.WorkflowConstants;
041    import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
042    import com.liferay.portal.model.Group;
043    import com.liferay.portal.model.ResourceConstants;
044    import com.liferay.portal.model.User;
045    import com.liferay.portal.model.WorkflowInstanceLink;
046    import com.liferay.portal.service.ServiceContext;
047    import com.liferay.portal.service.ServiceContextUtil;
048    import com.liferay.portal.theme.ThemeDisplay;
049    import com.liferay.portal.util.Portal;
050    import com.liferay.portal.util.PortalUtil;
051    import com.liferay.portal.util.PortletKeys;
052    import com.liferay.portal.util.PrefsPropsUtil;
053    import com.liferay.portal.util.PropsValues;
054    import com.liferay.portal.util.SubscriptionSender;
055    import com.liferay.portlet.asset.model.AssetEntry;
056    import com.liferay.portlet.asset.model.AssetLinkConstants;
057    import com.liferay.portlet.blogs.EntryContentException;
058    import com.liferay.portlet.blogs.EntryDisplayDateException;
059    import com.liferay.portlet.blogs.EntrySmallImageNameException;
060    import com.liferay.portlet.blogs.EntrySmallImageSizeException;
061    import com.liferay.portlet.blogs.EntryTitleException;
062    import com.liferay.portlet.blogs.model.BlogsEntry;
063    import com.liferay.portlet.blogs.service.base.BlogsEntryLocalServiceBaseImpl;
064    import com.liferay.portlet.blogs.social.BlogsActivityKeys;
065    import com.liferay.portlet.blogs.util.BlogsUtil;
066    import com.liferay.portlet.blogs.util.LinkbackProducerUtil;
067    import com.liferay.portlet.blogs.util.comparator.EntryDisplayDateComparator;
068    import com.liferay.portlet.social.model.SocialActivityConstants;
069    import com.liferay.portlet.trash.model.TrashEntry;
070    
071    import java.io.IOException;
072    import java.io.InputStream;
073    
074    import java.util.Date;
075    import java.util.HashMap;
076    import java.util.HashSet;
077    import java.util.List;
078    import java.util.Locale;
079    import java.util.Map;
080    import java.util.Set;
081    
082    import javax.portlet.PortletPreferences;
083    
084    import javax.servlet.http.HttpServletRequest;
085    
086    import net.htmlparser.jericho.Source;
087    import net.htmlparser.jericho.StartTag;
088    
089    /**
090     * The implementation of the blogs entry local service.
091     *
092     * @author Brian Wing Shun Chan
093     * @author Wilson S. Man
094     * @author Raymond Augé
095     * @author Thiago Moreira
096     * @author Juan Fernández
097     * @author Zsolt Berentey
098     */
099    public class BlogsEntryLocalServiceImpl extends BlogsEntryLocalServiceBaseImpl {
100    
101            public BlogsEntry addEntry(
102                            long userId, String title, String description, String content,
103                            int displayDateMonth, int displayDateDay, int displayDateYear,
104                            int displayDateHour, int displayDateMinute, boolean allowPingbacks,
105                            boolean allowTrackbacks, String[] trackbacks, boolean smallImage,
106                            String smallImageURL, String smallImageFileName,
107                            InputStream smallImageInputStream, ServiceContext serviceContext)
108                    throws PortalException, SystemException {
109    
110                    // Entry
111    
112                    User user = userPersistence.findByPrimaryKey(userId);
113                    long groupId = serviceContext.getScopeGroupId();
114    
115                    Date displayDate = PortalUtil.getDate(
116                            displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
117                            displayDateMinute, user.getTimeZone(),
118                            EntryDisplayDateException.class);
119    
120                    byte[] smallImageBytes = null;
121    
122                    try {
123                            if ((smallImageInputStream != null) && smallImage) {
124                                    smallImageBytes = FileUtil.getBytes(smallImageInputStream);
125                            }
126                    }
127                    catch (IOException ioe) {
128                    }
129    
130                    Date now = new Date();
131    
132                    validate(
133                            title, content, smallImage, smallImageURL, smallImageFileName,
134                            smallImageBytes);
135    
136                    long entryId = counterLocalService.increment();
137    
138                    BlogsEntry entry = blogsEntryPersistence.create(entryId);
139    
140                    entry.setUuid(serviceContext.getUuid());
141                    entry.setGroupId(groupId);
142                    entry.setCompanyId(user.getCompanyId());
143                    entry.setUserId(user.getUserId());
144                    entry.setUserName(user.getFullName());
145                    entry.setCreateDate(serviceContext.getCreateDate(now));
146                    entry.setModifiedDate(serviceContext.getModifiedDate(now));
147                    entry.setTitle(title);
148                    entry.setUrlTitle(
149                            getUniqueUrlTitle(entryId, title, null, serviceContext));
150                    entry.setDescription(description);
151                    entry.setContent(content);
152                    entry.setDisplayDate(displayDate);
153                    entry.setAllowPingbacks(allowPingbacks);
154                    entry.setAllowTrackbacks(allowTrackbacks);
155                    entry.setSmallImage(smallImage);
156                    entry.setSmallImageId(counterLocalService.increment());
157                    entry.setSmallImageURL(smallImageURL);
158                    entry.setStatus(WorkflowConstants.STATUS_DRAFT);
159                    entry.setStatusDate(serviceContext.getModifiedDate(now));
160                    entry.setExpandoBridgeAttributes(serviceContext);
161    
162                    blogsEntryPersistence.update(entry);
163    
164                    // Resources
165    
166                    if (serviceContext.isAddGroupPermissions() ||
167                            serviceContext.isAddGuestPermissions()) {
168    
169                            addEntryResources(
170                                    entry, serviceContext.isAddGroupPermissions(),
171                                    serviceContext.isAddGuestPermissions());
172                    }
173                    else {
174                            addEntryResources(
175                                    entry, serviceContext.getGroupPermissions(),
176                                    serviceContext.getGuestPermissions());
177                    }
178    
179                    // Small image
180    
181                    saveImages(smallImage, entry.getSmallImageId(), smallImageBytes);
182    
183                    // Asset
184    
185                    updateAsset(
186                            userId, entry, serviceContext.getAssetCategoryIds(),
187                            serviceContext.getAssetTagNames(),
188                            serviceContext.getAssetLinkEntryIds());
189    
190                    // Message boards
191    
192                    if (PropsValues.BLOGS_ENTRY_COMMENTS_ENABLED) {
193                            mbMessageLocalService.addDiscussionMessage(
194                                    userId, entry.getUserName(), groupId,
195                                    BlogsEntry.class.getName(), entryId,
196                                    WorkflowConstants.ACTION_PUBLISH);
197                    }
198    
199                    // Workflow
200    
201                    if ((trackbacks != null) && (trackbacks.length > 0)) {
202                            serviceContext.setAttribute("trackbacks", trackbacks);
203                    }
204                    else {
205                            serviceContext.setAttribute("trackbacks", null);
206                    }
207    
208                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
209                            user.getCompanyId(), groupId, userId, BlogsEntry.class.getName(),
210                            entry.getEntryId(), entry, serviceContext);
211    
212                    return entry;
213            }
214    
215            public void addEntryResources(
216                            BlogsEntry entry, boolean addGroupPermissions,
217                            boolean addGuestPermissions)
218                    throws PortalException, SystemException {
219    
220                    resourceLocalService.addResources(
221                            entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
222                            BlogsEntry.class.getName(), entry.getEntryId(), false,
223                            addGroupPermissions, addGuestPermissions);
224            }
225    
226            public void addEntryResources(
227                            BlogsEntry entry, String[] groupPermissions,
228                            String[] guestPermissions)
229                    throws PortalException, SystemException {
230    
231                    resourceLocalService.addModelResources(
232                            entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
233                            BlogsEntry.class.getName(), entry.getEntryId(), groupPermissions,
234                            guestPermissions);
235            }
236    
237            public void addEntryResources(
238                            long entryId, boolean addGroupPermissions,
239                            boolean addGuestPermissions)
240                    throws PortalException, SystemException {
241    
242                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
243    
244                    addEntryResources(entry, addGroupPermissions, addGuestPermissions);
245            }
246    
247            public void addEntryResources(
248                            long entryId, String[] groupPermissions, String[] guestPermissions)
249                    throws PortalException, SystemException {
250    
251                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
252    
253                    addEntryResources(entry, groupPermissions, guestPermissions);
254            }
255    
256            public void checkEntries() throws PortalException, SystemException {
257                    Date now = new Date();
258    
259                    int count = blogsEntryPersistence.countByLtD_S(
260                            now, WorkflowConstants.STATUS_SCHEDULED);
261    
262                    if (count == 0) {
263                            return;
264                    }
265    
266                    List<BlogsEntry> entries = blogsEntryPersistence.findByLtD_S(
267                            now, WorkflowConstants.STATUS_SCHEDULED);
268    
269                    for (BlogsEntry entry : entries) {
270                            ServiceContext serviceContext = new ServiceContext();
271    
272                            String[] trackbacks = StringUtil.split(entry.getTrackbacks());
273    
274                            serviceContext.setAttribute("trackbacks", trackbacks);
275    
276                            serviceContext.setCommand(Constants.UPDATE);
277    
278                            String layoutFullURL = PortalUtil.getLayoutFullURL(
279                                    entry.getGroupId(), PortletKeys.BLOGS);
280    
281                            serviceContext.setLayoutFullURL(layoutFullURL);
282    
283                            serviceContext.setScopeGroupId(entry.getGroupId());
284    
285                            updateStatus(
286                                    entry.getStatusByUserId(), entry.getEntryId(),
287                                    WorkflowConstants.STATUS_APPROVED, serviceContext);
288                    }
289            }
290    
291            public void deleteEntries(long groupId)
292                    throws PortalException, SystemException {
293    
294                    for (BlogsEntry entry : blogsEntryPersistence.findByGroupId(groupId)) {
295                            deleteEntry(entry);
296                    }
297            }
298    
299            public void deleteEntry(BlogsEntry entry)
300                    throws PortalException, SystemException {
301    
302                    // Entry
303    
304                    blogsEntryPersistence.remove(entry);
305    
306                    // Resources
307    
308                    resourceLocalService.deleteResource(
309                            entry.getCompanyId(), BlogsEntry.class.getName(),
310                            ResourceConstants.SCOPE_INDIVIDUAL, entry.getEntryId());
311    
312                    // Image
313    
314                    imageLocalService.deleteImage(entry.getSmallImageId());
315    
316                    // Subscriptions
317    
318                    subscriptionLocalService.deleteSubscriptions(
319                            entry.getCompanyId(), BlogsEntry.class.getName(),
320                            entry.getEntryId());
321    
322                    // Statistics
323    
324                    blogsStatsUserLocalService.updateStatsUser(
325                            entry.getGroupId(), entry.getUserId(), entry.getDisplayDate());
326    
327                    // Asset
328    
329                    assetEntryLocalService.deleteEntry(
330                            BlogsEntry.class.getName(), entry.getEntryId());
331    
332                    // Expando
333    
334                    expandoValueLocalService.deleteValues(
335                            BlogsEntry.class.getName(), entry.getEntryId());
336    
337                    // Message boards
338    
339                    mbMessageLocalService.deleteDiscussionMessages(
340                            BlogsEntry.class.getName(), entry.getEntryId());
341    
342                    // Ratings
343    
344                    ratingsStatsLocalService.deleteStats(
345                            BlogsEntry.class.getName(), entry.getEntryId());
346    
347                    // Trash
348    
349                    trashEntryLocalService.deleteEntry(
350                            BlogsEntry.class.getName(), entry.getEntryId());
351    
352                    // Indexer
353    
354                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
355                            BlogsEntry.class);
356    
357                    indexer.delete(entry);
358    
359                    // Workflow
360    
361                    workflowInstanceLinkLocalService.deleteWorkflowInstanceLinks(
362                            entry.getCompanyId(), entry.getGroupId(),
363                            BlogsEntry.class.getName(), entry.getEntryId());
364            }
365    
366            public void deleteEntry(long entryId)
367                    throws PortalException, SystemException {
368    
369                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
370    
371                    deleteEntry(entry);
372            }
373    
374            /**
375             * @deprecated {@link #getCompanyEntries(long, Date, QueryDefinition)}
376             */
377            public List<BlogsEntry> getCompanyEntries(
378                            long companyId, Date displayDate, int status, int start, int end)
379                    throws SystemException {
380    
381                    QueryDefinition queryDefinition = new QueryDefinition(
382                            status, start, end, null);
383    
384                    return getCompanyEntries(companyId, displayDate, queryDefinition);
385            }
386    
387            /**
388             * @deprecated {@link #getCompanyEntries(long, Date, QueryDefinition)}
389             */
390            public List<BlogsEntry> getCompanyEntries(
391                            long companyId, Date displayDate, int status, int start, int end,
392                            OrderByComparator obc)
393                    throws SystemException {
394    
395                    QueryDefinition queryDefinition = new QueryDefinition(
396                            status, start, end, obc);
397    
398                    return getCompanyEntries(companyId, displayDate, queryDefinition);
399            }
400    
401            public List<BlogsEntry> getCompanyEntries(
402                            long companyId, Date displayDate, QueryDefinition queryDefinition)
403                    throws SystemException {
404    
405                    if (queryDefinition.isExcludeStatus()) {
406                            return blogsEntryPersistence.findByC_LtD_NotS(
407                                    companyId, displayDate, queryDefinition.getStatus(),
408                                    queryDefinition.getStart(), queryDefinition.getEnd(),
409                                    queryDefinition.getOrderByComparator());
410                    }
411                    else {
412                            return blogsEntryPersistence.findByC_LtD_S(
413                                    companyId, displayDate, queryDefinition.getStatus(),
414                                    queryDefinition.getStart(), queryDefinition.getEnd(),
415                                    queryDefinition.getOrderByComparator());
416                    }
417            }
418    
419            /**
420             * @deprecated {@link #getCompanyEntriesCount(long, Date, QueryDefinition)}
421             */
422            public int getCompanyEntriesCount(
423                            long companyId, Date displayDate, int status)
424                    throws SystemException {
425    
426                    QueryDefinition queryDefinition = new QueryDefinition(status);
427    
428                    return getCompanyEntriesCount(companyId, displayDate, queryDefinition);
429            }
430    
431            public int getCompanyEntriesCount(
432                            long companyId, Date displayDate, QueryDefinition queryDefinition)
433                    throws SystemException {
434    
435                    if (queryDefinition.isExcludeStatus()) {
436                            return blogsEntryPersistence.countByC_LtD_NotS(
437                                    companyId, displayDate, queryDefinition.getStatus());
438                    }
439                    else {
440                            return blogsEntryPersistence.countByC_LtD_S(
441                                    companyId, displayDate, queryDefinition.getStatus());
442                    }
443            }
444    
445            public BlogsEntry[] getEntriesPrevAndNext(long entryId)
446                    throws PortalException, SystemException {
447    
448                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
449    
450                    return blogsEntryPersistence.findByG_S_PrevAndNext(
451                            entry.getEntryId(), entry.getGroupId(),
452                            WorkflowConstants.STATUS_APPROVED,
453                            new EntryDisplayDateComparator(true));
454            }
455    
456            public BlogsEntry getEntry(long entryId)
457                    throws PortalException, SystemException {
458    
459                    return blogsEntryPersistence.findByPrimaryKey(entryId);
460            }
461    
462            public BlogsEntry getEntry(long groupId, String urlTitle)
463                    throws PortalException, SystemException {
464    
465                    return blogsEntryPersistence.findByG_UT(groupId, urlTitle);
466            }
467    
468            /**
469             * @deprecated {@link #getGroupEntries(long, Date, QueryDefinition)}
470             */
471            public List<BlogsEntry> getGroupEntries(
472                            long groupId, Date displayDate, int status, int start, int end)
473                    throws SystemException {
474    
475                    QueryDefinition queryDefinition = new QueryDefinition(
476                            status, start, end, null);
477    
478                    return getGroupEntries(groupId, displayDate, queryDefinition);
479            }
480    
481            /**
482             * @deprecated {@link #getGroupEntries(long, Date, QueryDefinition)}
483             */
484            public List<BlogsEntry> getGroupEntries(
485                            long groupId, Date displayDate, int status, int start, int end,
486                            OrderByComparator obc)
487                    throws SystemException {
488    
489                    QueryDefinition queryDefinition = new QueryDefinition(
490                            status, start, end, obc);
491    
492                    return getGroupEntries(groupId, displayDate, queryDefinition);
493            }
494    
495            public List<BlogsEntry> getGroupEntries(
496                            long groupId, Date displayDate, QueryDefinition queryDefinition)
497                    throws SystemException {
498    
499                    if (queryDefinition.isExcludeStatus()) {
500                            return blogsEntryPersistence.findByG_LtD_NotS(
501                                    groupId, displayDate, queryDefinition.getStatus(),
502                                    queryDefinition.getStart(), queryDefinition.getEnd(),
503                                    queryDefinition.getOrderByComparator());
504                    }
505                    else {
506                            return blogsEntryPersistence.findByG_LtD_S(
507                                    groupId, displayDate, queryDefinition.getStatus(),
508                                    queryDefinition.getStart(), queryDefinition.getEnd(),
509                                    queryDefinition.getOrderByComparator());
510                    }
511            }
512    
513            /**
514             * @deprecated {@link #getGroupEntries(long, QueryDefinition)}
515             */
516            public List<BlogsEntry> getGroupEntries(
517                            long groupId, int status, int start, int end)
518                    throws SystemException {
519    
520                    QueryDefinition queryDefinition = new QueryDefinition(
521                            status, start, end, null);
522    
523                    return getGroupEntries(groupId, queryDefinition);
524            }
525    
526            /**
527             * @deprecated {@link #getGroupEntries(long, QueryDefinition)}
528             */
529            public List<BlogsEntry> getGroupEntries(
530                            long groupId, int status, int start, int end, OrderByComparator obc)
531                    throws SystemException {
532    
533                    QueryDefinition queryDefinition = new QueryDefinition(
534                            status, start, end, obc);
535    
536                    return getGroupEntries(groupId, queryDefinition);
537            }
538    
539            public List<BlogsEntry> getGroupEntries(
540                            long groupId, QueryDefinition queryDefinition)
541                    throws SystemException {
542    
543                    if (queryDefinition.isExcludeStatus()) {
544                            return blogsEntryPersistence.findByG_NotS(
545                                    groupId, queryDefinition.getStatus(),
546                                    queryDefinition.getStart(), queryDefinition.getEnd(),
547                                    queryDefinition.getOrderByComparator());
548                    }
549                    else {
550                            return blogsEntryPersistence.findByG_S(
551                                    groupId, queryDefinition.getStatus(),
552                                    queryDefinition.getStart(), queryDefinition.getEnd(),
553                                    queryDefinition.getOrderByComparator());
554                    }
555            }
556    
557            /**
558             * @deprecated {@link #getGroupEntriesCount(long, Date, QueryDefinition)}
559             */
560            public int getGroupEntriesCount(long groupId, Date displayDate, int status)
561                    throws SystemException {
562    
563                    QueryDefinition queryDefinition = new QueryDefinition(status);
564    
565                    return getGroupEntriesCount(groupId, displayDate, queryDefinition);
566            }
567    
568            public int getGroupEntriesCount(
569                            long groupId, Date displayDate, QueryDefinition queryDefinition)
570                    throws SystemException {
571    
572                    if (queryDefinition.isExcludeStatus()) {
573                            return blogsEntryPersistence.countByG_LtD_NotS(
574                                    groupId, displayDate, queryDefinition.getStatus());
575                    }
576                    else {
577                            return blogsEntryPersistence.countByG_LtD_S(
578                                    groupId, displayDate, queryDefinition.getStatus());
579                    }
580            }
581    
582            /**
583             * @deprecated {@link #getGroupEntriesCount(long, QueryDefinition)}
584             */
585            public int getGroupEntriesCount(long groupId, int status)
586                    throws SystemException {
587    
588                    QueryDefinition queryDefinition = new QueryDefinition(status);
589    
590                    return getGroupEntriesCount(groupId, queryDefinition);
591            }
592    
593            public int getGroupEntriesCount(
594                            long groupId, QueryDefinition queryDefinition)
595                    throws SystemException {
596    
597                    if (queryDefinition.isExcludeStatus()) {
598                            return blogsEntryPersistence.countByG_NotS(
599                                    groupId, queryDefinition.getStatus());
600                    }
601                    else {
602                            return blogsEntryPersistence.countByG_S(
603                                    groupId, queryDefinition.getStatus());
604                    }
605            }
606    
607            /**
608             * @deprecated {@link #getGroupsEntries(long, long, Date, QueryDefinition)}
609             */
610            public List<BlogsEntry> getGroupsEntries(
611                            long companyId, long groupId, Date displayDate, int status,
612                            int start, int end)
613                    throws SystemException {
614    
615                    QueryDefinition queryDefinition = new QueryDefinition(
616                            status, start, end, null);
617    
618                    return getGroupsEntries(
619                            companyId, groupId, displayDate, queryDefinition);
620            }
621    
622            public List<BlogsEntry> getGroupsEntries(
623                            long companyId, long groupId, Date displayDate,
624                            QueryDefinition queryDefinition)
625                    throws SystemException {
626    
627                    return blogsEntryFinder.findByGroupIds(
628                            companyId, groupId, displayDate, queryDefinition);
629            }
630    
631            /**
632             * @deprecated {@link #getGroupUserEntries(long, long, Date,
633             *             QueryDefinition)}
634             */
635            public List<BlogsEntry> getGroupUserEntries(
636                            long groupId, long userId, Date displayDate, int status, int start,
637                            int end)
638                    throws SystemException {
639    
640                    QueryDefinition queryDefinition = new QueryDefinition(
641                            status, start, end, null);
642    
643                    return getGroupUserEntries(
644                            groupId, userId, displayDate, queryDefinition);
645            }
646    
647            /**
648             * @deprecated {@link #getGroupUserEntries(long, long, Date,
649             *             QueryDefinition)}
650             */
651            public List<BlogsEntry> getGroupUserEntries(
652                            long groupId, long userId, Date displayDate, int status, int start,
653                            int end, OrderByComparator obc)
654                    throws SystemException {
655    
656                    QueryDefinition queryDefinition = new QueryDefinition(
657                            status, start, end, obc);
658    
659                    return getGroupUserEntries(
660                            groupId, userId, displayDate, queryDefinition);
661            }
662    
663            public List<BlogsEntry> getGroupUserEntries(
664                            long groupId, long userId, Date displayDate,
665                            QueryDefinition queryDefinition)
666                    throws SystemException {
667    
668                    if (queryDefinition.isExcludeStatus()) {
669                            return blogsEntryPersistence.findByG_U_NotS(
670                                    groupId, userId, queryDefinition.getStatus(),
671                                    queryDefinition.getStart(), queryDefinition.getEnd(),
672                                    queryDefinition.getOrderByComparator());
673                    }
674                    else {
675                            return blogsEntryPersistence.findByG_U_S(
676                                    groupId, userId, queryDefinition.getStatus(),
677                                    queryDefinition.getStart(), queryDefinition.getEnd(),
678                                    queryDefinition.getOrderByComparator());
679                    }
680            }
681    
682            /**
683             * @deprecated {@link #getGroupUserEntriesCount(long, long, Date,
684             *             QueryDefinition)}
685             */
686            public int getGroupUserEntriesCount(
687                            long groupId, long userId, Date displayDate, int status)
688                    throws SystemException {
689    
690                    QueryDefinition queryDefinition = new QueryDefinition(status);
691    
692                    return getGroupUserEntriesCount(
693                            groupId, userId, displayDate, queryDefinition);
694            }
695    
696            public int getGroupUserEntriesCount(
697                            long groupId, long userId, Date displayDate,
698                            QueryDefinition queryDefinition)
699                    throws SystemException {
700    
701                    if (queryDefinition.isExcludeStatus()) {
702                            return blogsEntryPersistence.countByG_U_LtD_NotS(
703                                    groupId, userId, displayDate, queryDefinition.getStatus());
704                    }
705                    else {
706                            return blogsEntryPersistence.countByG_U_LtD_S(
707                                    groupId, userId, displayDate, queryDefinition.getStatus());
708                    }
709            }
710    
711            public List<BlogsEntry> getNoAssetEntries() throws SystemException {
712                    return blogsEntryFinder.findByNoAssets();
713            }
714    
715            /**
716             * @deprecated {@link #getOrganizationEntries(long, Date, QueryDefinition)}
717             */
718            public List<BlogsEntry> getOrganizationEntries(
719                            long organizationId, Date displayDate, int status, int start,
720                            int end)
721                    throws SystemException {
722    
723                    QueryDefinition queryDefinition = new QueryDefinition(
724                            status, start, end, null);
725    
726                    return getOrganizationEntries(
727                            organizationId, displayDate, queryDefinition);
728            }
729    
730            /**
731             * @deprecated {@link #getOrganizationEntries(long, Date, QueryDefinition)}
732             */
733            public List<BlogsEntry> getOrganizationEntries(
734                            long organizationId, Date displayDate, int status, int start,
735                            int end, OrderByComparator obc)
736                    throws SystemException {
737    
738                    QueryDefinition queryDefinition = new QueryDefinition(
739                            status, start, end, obc);
740    
741                    return getOrganizationEntries(
742                            organizationId, displayDate, queryDefinition);
743            }
744    
745            public List<BlogsEntry> getOrganizationEntries(
746                            long organizationId, Date displayDate,
747                            QueryDefinition queryDefinition)
748                    throws SystemException {
749    
750                    return blogsEntryFinder.findByOrganizationId(
751                            organizationId, displayDate, queryDefinition);
752            }
753    
754            /**
755             * @deprecated {@link #getOrganizationEntriesCount(long, Date,
756             *             QueryDefinition)}
757             */
758            public int getOrganizationEntriesCount(
759                            long organizationId, Date displayDate, int status)
760                    throws SystemException {
761    
762                    QueryDefinition queryDefinition = new QueryDefinition(status);
763    
764                    return getOrganizationEntriesCount(
765                            organizationId, displayDate, queryDefinition);
766            }
767    
768            public int getOrganizationEntriesCount(
769                            long organizationId, Date displayDate,
770                            QueryDefinition queryDefinition)
771                    throws SystemException {
772    
773                    return blogsEntryFinder.countByOrganizationId(
774                            organizationId, displayDate, queryDefinition);
775            }
776    
777            public void moveEntriesToTrash(long groupId, long userId)
778                    throws PortalException, SystemException {
779    
780                    List<BlogsEntry> entries = blogsEntryPersistence.findByGroupId(groupId);
781    
782                    for (BlogsEntry entry : entries) {
783                            moveEntryToTrash(userId, entry);
784                    }
785            }
786    
787            /**
788             * Moves the blogs entry to the recycle bin. Social activity counters for
789             * this entry get disabled.
790             *
791             * @param  userId the primary key of the user moving the blogs entry
792             * @param  entry the blogs entry to be moved
793             * @return the moved blogs entry
794             * @throws PortalException if a user with the primary key could not be found
795             *         or if the blogs entry owner's social activity counter could not
796             *         be updated
797             * @throws SystemException if a system exception occurred
798             */
799            public BlogsEntry moveEntryToTrash(long userId, BlogsEntry entry)
800                    throws PortalException, SystemException {
801    
802                    // Entry
803    
804                    int oldStatus = entry.getStatus();
805    
806                    if (oldStatus == WorkflowConstants.STATUS_PENDING) {
807                            entry.setStatus(WorkflowConstants.STATUS_DRAFT);
808    
809                            blogsEntryPersistence.update(entry);
810                    }
811    
812                    updateStatus(
813                            userId, entry.getEntryId(), WorkflowConstants.STATUS_IN_TRASH,
814                            new ServiceContext());
815    
816                    // Social
817    
818                    socialActivityCounterLocalService.disableActivityCounters(
819                            BlogsEntry.class.getName(), entry.getEntryId());
820    
821                    socialActivityLocalService.addActivity(
822                            userId, entry.getGroupId(), BlogsEntry.class.getName(),
823                            entry.getEntryId(), SocialActivityConstants.TYPE_MOVE_TO_TRASH,
824                            StringPool.BLANK, 0);
825    
826                    // Workflow
827    
828                    if (oldStatus == WorkflowConstants.STATUS_PENDING) {
829                            WorkflowInstanceLink workflowInstanceLink =
830                                    workflowInstanceLinkLocalService.getWorkflowInstanceLink(
831                                            entry.getCompanyId(), entry.getGroupId(),
832                                            BlogsEntry.class.getName(), entry.getEntryId());
833    
834                            workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
835                                    workflowInstanceLink.getWorkflowInstanceLinkId());
836                    }
837    
838                    return entry;
839            }
840    
841            /**
842             * Moves the blogs entry with the ID to the recycle bin.
843             *
844             * @param  userId the primary key of the user moving the blogs entry
845             * @param  entryId the primary key of the blogs entry to be moved
846             * @return the moved blogs entry
847             * @throws PortalException if a user or blogs entry with the primary key
848             *         could not be found or if the blogs entry owner's social activity
849             *         counter could not be updated
850             * @throws SystemException if a system exception occurred
851             */
852            public BlogsEntry moveEntryToTrash(long userId, long entryId)
853                    throws PortalException, SystemException {
854    
855                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
856    
857                    return moveEntryToTrash(userId, entry);
858            }
859    
860            /**
861             * Restores the blogs entry with the ID from the recycle bin. Social
862             * activity counters for this entry get activated.
863             *
864             * @param  userId the primary key of the user restoring the blogs entry
865             * @param  entryId the primary key of the blogs entry to be restored
866             * @throws PortalException if a user or blogs entry with the primary key
867             *         could not be found or if the blogs entry owner's social activity
868             *         counter could not be updated
869             * @throws SystemException if a system exception occurred
870             */
871            public void restoreEntryFromTrash(long userId, long entryId)
872                    throws PortalException, SystemException {
873    
874                    // Entry
875    
876                    TrashEntry trashEntry = trashEntryLocalService.getEntry(
877                            BlogsEntry.class.getName(), entryId);
878    
879                    updateStatus(
880                            userId, entryId, trashEntry.getStatus(), new ServiceContext());
881    
882                    // Social
883    
884                    socialActivityCounterLocalService.enableActivityCounters(
885                            BlogsEntry.class.getName(), entryId);
886    
887                    socialActivityLocalService.addActivity(
888                            userId, trashEntry.getGroupId(), BlogsEntry.class.getName(),
889                            entryId, SocialActivityConstants.TYPE_RESTORE_FROM_TRASH,
890                            StringPool.BLANK, 0);
891            }
892    
893            public void subscribe(long userId, long groupId)
894                    throws PortalException, SystemException {
895    
896                    subscriptionLocalService.addSubscription(
897                            userId, groupId, BlogsEntry.class.getName(), groupId);
898            }
899    
900            public void unsubscribe(long userId, long groupId)
901                    throws PortalException, SystemException {
902    
903                    subscriptionLocalService.deleteSubscription(
904                            userId, BlogsEntry.class.getName(), groupId);
905            }
906    
907            public void updateAsset(
908                            long userId, BlogsEntry entry, long[] assetCategoryIds,
909                            String[] assetTagNames, long[] assetLinkEntryIds)
910                    throws PortalException, SystemException {
911    
912                    boolean visible = false;
913    
914                    if (entry.isApproved()) {
915                            visible = true;
916                    }
917    
918                    String summary = HtmlUtil.extractText(
919                            StringUtil.shorten(entry.getContent(), 500));
920    
921                    AssetEntry assetEntry = assetEntryLocalService.updateEntry(
922                            userId, entry.getGroupId(), entry.getCreateDate(),
923                            entry.getModifiedDate(), BlogsEntry.class.getName(),
924                            entry.getEntryId(), entry.getUuid(), 0, assetCategoryIds,
925                            assetTagNames, visible, null, null, null, ContentTypes.TEXT_HTML,
926                            entry.getTitle(), entry.getDescription(), summary, null, null, 0, 0,
927                            null, false);
928    
929                    assetLinkLocalService.updateLinks(
930                            userId, assetEntry.getEntryId(), assetLinkEntryIds,
931                            AssetLinkConstants.TYPE_RELATED);
932            }
933    
934            public BlogsEntry updateEntry(
935                            long userId, long entryId, String title, String description,
936                            String content, int displayDateMonth, int displayDateDay,
937                            int displayDateYear, int displayDateHour, int displayDateMinute,
938                            boolean allowPingbacks, boolean allowTrackbacks,
939                            String[] trackbacks, boolean smallImage, String smallImageURL,
940                            String smallImageFileName, InputStream smallImageInputStream,
941                            ServiceContext serviceContext)
942                    throws PortalException, SystemException {
943    
944                    // Entry
945    
946                    User user = userPersistence.findByPrimaryKey(userId);
947    
948                    Date displayDate = PortalUtil.getDate(
949                            displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
950                            displayDateMinute, user.getTimeZone(),
951                            EntryDisplayDateException.class);
952    
953                    byte[] smallImageBytes = null;
954    
955                    try {
956                            if ((smallImageInputStream != null) && smallImage) {
957                                    smallImageBytes = FileUtil.getBytes(smallImageInputStream);
958                            }
959                    }
960                    catch (IOException ioe) {
961                    }
962    
963                    validate(
964                            title, content, smallImage, smallImageURL, smallImageFileName,
965                            smallImageBytes);
966    
967                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
968    
969                    String oldUrlTitle = entry.getUrlTitle();
970    
971                    entry.setModifiedDate(serviceContext.getModifiedDate(null));
972                    entry.setTitle(title);
973                    entry.setUrlTitle(
974                            getUniqueUrlTitle(entryId, title, oldUrlTitle, serviceContext));
975                    entry.setDescription(description);
976                    entry.setContent(content);
977                    entry.setDisplayDate(displayDate);
978                    entry.setAllowPingbacks(allowPingbacks);
979                    entry.setAllowTrackbacks(allowTrackbacks);
980                    entry.setSmallImage(smallImage);
981    
982                    if (entry.getSmallImageId() == 0) {
983                            entry.setSmallImageId(counterLocalService.increment());
984                    }
985    
986                    entry.setSmallImageURL(smallImageURL);
987    
988                    if (entry.isPending() || entry.isDraft()) {
989                    }
990                    else {
991                            entry.setStatus(WorkflowConstants.STATUS_DRAFT);
992                    }
993    
994                    entry.setExpandoBridgeAttributes(serviceContext);
995    
996                    blogsEntryPersistence.update(entry);
997    
998                    // Resources
999    
1000                    if ((serviceContext.getGroupPermissions() != null) ||
1001                            (serviceContext.getGuestPermissions() != null)) {
1002    
1003                            updateEntryResources(
1004                                    entry, serviceContext.getGroupPermissions(),
1005                                    serviceContext.getGuestPermissions());
1006                    }
1007    
1008                    // Small image
1009    
1010                    saveImages(smallImage, entry.getSmallImageId(), smallImageBytes);
1011    
1012                    // Asset
1013    
1014                    updateAsset(
1015                            userId, entry, serviceContext.getAssetCategoryIds(),
1016                            serviceContext.getAssetTagNames(),
1017                            serviceContext.getAssetLinkEntryIds());
1018    
1019                    // Workflow
1020    
1021                    boolean pingOldTrackbacks = false;
1022    
1023                    if (!oldUrlTitle.equals(entry.getUrlTitle())) {
1024                            pingOldTrackbacks = true;
1025                    }
1026    
1027                    serviceContext.setAttribute(
1028                            "pingOldTrackbacks", String.valueOf(pingOldTrackbacks));
1029    
1030                    if (Validator.isNotNull(trackbacks)) {
1031                            serviceContext.setAttribute("trackbacks", trackbacks);
1032                    }
1033                    else {
1034                            serviceContext.setAttribute("trackbacks", null);
1035                    }
1036    
1037                    WorkflowHandlerRegistryUtil.startWorkflowInstance(
1038                            user.getCompanyId(), entry.getGroupId(), userId,
1039                            BlogsEntry.class.getName(), entry.getEntryId(), entry,
1040                            serviceContext);
1041    
1042                    return entry;
1043            }
1044    
1045            public void updateEntryResources(
1046                            BlogsEntry entry, String[] groupPermissions,
1047                            String[] guestPermissions)
1048                    throws PortalException, SystemException {
1049    
1050                    resourceLocalService.updateResources(
1051                            entry.getCompanyId(), entry.getGroupId(),
1052                            BlogsEntry.class.getName(), entry.getEntryId(), groupPermissions,
1053                            guestPermissions);
1054            }
1055    
1056            public BlogsEntry updateStatus(
1057                            long userId, long entryId, int status,
1058                            ServiceContext serviceContext)
1059                    throws PortalException, SystemException {
1060    
1061                    // Entry
1062    
1063                    User user = userPersistence.findByPrimaryKey(userId);
1064                    Date now = new Date();
1065    
1066                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
1067    
1068                    int oldStatus = entry.getStatus();
1069    
1070                    if ((status == WorkflowConstants.STATUS_APPROVED) &&
1071                            now.before(entry.getDisplayDate())) {
1072    
1073                            status = WorkflowConstants.STATUS_SCHEDULED;
1074                    }
1075    
1076                    entry.setModifiedDate(serviceContext.getModifiedDate(now));
1077                    entry.setStatus(status);
1078                    entry.setStatusByUserId(user.getUserId());
1079                    entry.setStatusByUserName(user.getFullName());
1080                    entry.setStatusDate(serviceContext.getModifiedDate(now));
1081    
1082                    blogsEntryPersistence.update(entry);
1083    
1084                    // Statistics
1085    
1086                    blogsStatsUserLocalService.updateStatsUser(
1087                            entry.getGroupId(), entry.getUserId(), entry.getDisplayDate());
1088    
1089                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
1090                            BlogsEntry.class);
1091    
1092                    AssetEntry assetEntry = assetEntryLocalService.fetchEntry(
1093                            BlogsEntry.class.getName(), entryId);
1094    
1095                    if ((assetEntry == null) || (assetEntry.getPublishDate() == null)) {
1096                            serviceContext.setCommand(Constants.ADD);
1097                    }
1098    
1099                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1100    
1101                    extraDataJSONObject.put("title", entry.getTitle());
1102    
1103                    if (status == WorkflowConstants.STATUS_APPROVED) {
1104    
1105                            // Asset
1106    
1107                            assetEntryLocalService.updateEntry(
1108                                    BlogsEntry.class.getName(), entryId, entry.getDisplayDate(),
1109                                    true);
1110    
1111                            // Social
1112    
1113                            if ((oldStatus != WorkflowConstants.STATUS_IN_TRASH) &&
1114                                    (oldStatus != WorkflowConstants.STATUS_SCHEDULED)) {
1115    
1116                                    if (serviceContext.isCommandUpdate()) {
1117                                            socialActivityLocalService.addActivity(
1118                                                    user.getUserId(), entry.getGroupId(),
1119                                                    BlogsEntry.class.getName(), entryId,
1120                                                    BlogsActivityKeys.UPDATE_ENTRY,
1121                                                    extraDataJSONObject.toString(), 0);
1122                                    }
1123                                    else {
1124                                            socialActivityLocalService.addUniqueActivity(
1125                                                    user.getUserId(), entry.getGroupId(),
1126                                                    BlogsEntry.class.getName(), entryId,
1127                                                    BlogsActivityKeys.ADD_ENTRY,
1128                                                    extraDataJSONObject.toString(), 0);
1129                                    }
1130                            }
1131    
1132                            // Trash
1133    
1134                            if (oldStatus == WorkflowConstants.STATUS_IN_TRASH) {
1135                                    trashEntryLocalService.deleteEntry(
1136                                            BlogsEntry.class.getName(), entryId);
1137                            }
1138    
1139                            // Indexer
1140    
1141                            indexer.reindex(entry);
1142    
1143                            if (oldStatus != WorkflowConstants.STATUS_IN_TRASH) {
1144    
1145                                    // Subscriptions
1146    
1147                                    notifySubscribers(entry, serviceContext);
1148    
1149                                    // Ping
1150    
1151                                    String[] trackbacks = (String[])serviceContext.getAttribute(
1152                                            "trackbacks");
1153                                    Boolean pingOldTrackbacks = ParamUtil.getBoolean(
1154                                            serviceContext, "pingOldTrackbacks");
1155    
1156                                    pingGoogle(entry, serviceContext);
1157                                    pingPingback(entry, serviceContext);
1158                                    pingTrackbacks(
1159                                            entry, trackbacks, pingOldTrackbacks, serviceContext);
1160                            }
1161                    }
1162                    else {
1163    
1164                            // Asset
1165    
1166                            assetEntryLocalService.updateVisible(
1167                                    BlogsEntry.class.getName(), entryId, false);
1168    
1169                            // Social
1170    
1171                            if ((status == WorkflowConstants.STATUS_SCHEDULED) &&
1172                                    (oldStatus != WorkflowConstants.STATUS_IN_TRASH)) {
1173    
1174                                    if (serviceContext.isCommandUpdate()) {
1175                                            socialActivityLocalService.addActivity(
1176                                                    user.getUserId(), entry.getGroupId(),
1177                                                    BlogsEntry.class.getName(), entryId,
1178                                                    BlogsActivityKeys.UPDATE_ENTRY,
1179                                                    extraDataJSONObject.toString(), 0);
1180                                    }
1181                                    else {
1182                                            socialActivityLocalService.addUniqueActivity(
1183                                                    user.getUserId(), entry.getGroupId(),
1184                                                    BlogsEntry.class.getName(), entryId,
1185                                                    BlogsActivityKeys.ADD_ENTRY,
1186                                                    extraDataJSONObject.toString(), 0);
1187                                    }
1188                            }
1189    
1190                            // Trash
1191    
1192                            if (status == WorkflowConstants.STATUS_IN_TRASH) {
1193                                    trashEntryLocalService.addTrashEntry(
1194                                            userId, entry.getGroupId(), BlogsEntry.class.getName(),
1195                                            entry.getEntryId(), oldStatus, null, null);
1196                            }
1197                            else if (oldStatus == WorkflowConstants.STATUS_IN_TRASH) {
1198                                    trashEntryLocalService.deleteEntry(
1199                                            BlogsEntry.class.getName(), entryId);
1200                            }
1201    
1202                            // Indexer
1203    
1204                            if (status == WorkflowConstants.STATUS_IN_TRASH) {
1205                                    indexer.reindex(entry);
1206                            }
1207                            else {
1208                                    indexer.delete(entry);
1209                            }
1210                    }
1211    
1212                    return entry;
1213            }
1214    
1215            protected String getUniqueUrlTitle(long entryId, long groupId, String title)
1216                    throws SystemException {
1217    
1218                    String urlTitle = BlogsUtil.getUrlTitle(entryId, title);
1219    
1220                    for (int i = 1;; i++) {
1221                            BlogsEntry entry = blogsEntryPersistence.fetchByG_UT(
1222                                    groupId, urlTitle);
1223    
1224                            if ((entry == null) || (entryId == entry.getEntryId())) {
1225                                    break;
1226                            }
1227                            else {
1228                                    String suffix = StringPool.DASH + i;
1229    
1230                                    String prefix = urlTitle;
1231    
1232                                    if (urlTitle.length() > suffix.length()) {
1233                                            prefix = urlTitle.substring(
1234                                                    0, urlTitle.length() - suffix.length());
1235                                    }
1236    
1237                                    urlTitle = prefix + suffix;
1238                            }
1239                    }
1240    
1241                    return urlTitle;
1242            }
1243    
1244            protected String getUniqueUrlTitle(
1245                            long entryId, String title, String oldUrlTitle,
1246                            ServiceContext serviceContext)
1247                    throws SystemException {
1248    
1249                    String serviceContextUrlTitle = ParamUtil.getString(
1250                            serviceContext, "urlTitle");
1251    
1252                    String urlTitle = null;
1253    
1254                    if (Validator.isNotNull(serviceContextUrlTitle)) {
1255                            urlTitle = BlogsUtil.getUrlTitle(entryId, serviceContextUrlTitle);
1256                    }
1257                    else if (Validator.isNotNull(oldUrlTitle)) {
1258                            return oldUrlTitle;
1259                    }
1260                    else {
1261                            urlTitle = getUniqueUrlTitle(
1262                                    entryId, serviceContext.getScopeGroupId(), title);
1263                    }
1264    
1265                    BlogsEntry urlTitleEntry = blogsEntryPersistence.fetchByG_UT(
1266                            serviceContext.getScopeGroupId(), urlTitle);
1267    
1268                    if ((urlTitleEntry != null) &&
1269                            (urlTitleEntry.getEntryId() != entryId)) {
1270    
1271                            urlTitle = getUniqueUrlTitle(
1272                                    entryId, serviceContext.getScopeGroupId(), urlTitle);
1273                    }
1274    
1275                    return urlTitle;
1276            }
1277    
1278            protected void notifySubscribers(
1279                            BlogsEntry entry, ServiceContext serviceContext)
1280                    throws SystemException {
1281    
1282                    if (!entry.isApproved()) {
1283                            return;
1284                    }
1285    
1286                    String layoutFullURL = serviceContext.getLayoutFullURL();
1287    
1288                    if (Validator.isNull(layoutFullURL)) {
1289                            return;
1290                    }
1291    
1292                    PortletPreferences preferences =
1293                            ServiceContextUtil.getPortletPreferences(serviceContext);
1294    
1295                    if (preferences == null) {
1296                            long ownerId = entry.getGroupId();
1297                            int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
1298                            long plid = PortletKeys.PREFS_PLID_SHARED;
1299                            String portletId = PortletKeys.BLOGS;
1300                            String defaultPreferences = null;
1301    
1302                            preferences = portletPreferencesLocalService.getPreferences(
1303                                    entry.getCompanyId(), ownerId, ownerType, plid, portletId,
1304                                    defaultPreferences);
1305                    }
1306    
1307                    if (serviceContext.isCommandAdd() &&
1308                            BlogsUtil.getEmailEntryAddedEnabled(preferences)) {
1309                    }
1310                    else if (serviceContext.isCommandUpdate() &&
1311                            BlogsUtil.getEmailEntryUpdatedEnabled(preferences)) {
1312                    }
1313                    else {
1314                            return;
1315                    }
1316    
1317                    String entryURL =
1318                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs" +
1319                                    StringPool.SLASH + entry.getEntryId();
1320    
1321                    String fromName = BlogsUtil.getEmailFromName(
1322                            preferences, entry.getCompanyId());
1323                    String fromAddress = BlogsUtil.getEmailFromAddress(
1324                            preferences, entry.getCompanyId());
1325    
1326                    Map<Locale, String> localizedSubjectMap = null;
1327                    Map<Locale, String> localizedBodyMap = null;
1328    
1329                    if (serviceContext.isCommandUpdate()) {
1330                            localizedSubjectMap = BlogsUtil.getEmailEntryUpdatedSubjectMap(
1331                                    preferences);
1332                            localizedBodyMap = BlogsUtil.getEmailEntryUpdatedBodyMap(
1333                                    preferences);
1334                    }
1335                    else {
1336                            localizedSubjectMap = BlogsUtil.getEmailEntryAddedSubjectMap(
1337                                    preferences);
1338                            localizedBodyMap = BlogsUtil.getEmailEntryAddedBodyMap(preferences);
1339                    }
1340    
1341                    SubscriptionSender subscriptionSender = new SubscriptionSender();
1342    
1343                    subscriptionSender.setCompanyId(entry.getCompanyId());
1344                    subscriptionSender.setContextAttributes(
1345                            "[$BLOGS_ENTRY_STATUS_BY_USER_NAME$]", entry.getStatusByUserName(),
1346                            "[$BLOGS_ENTRY_URL$]", entryURL);
1347                    subscriptionSender.setContextUserPrefix("BLOGS_ENTRY");
1348                    subscriptionSender.setFrom(fromAddress, fromName);
1349                    subscriptionSender.setHtmlFormat(true);
1350                    subscriptionSender.setLocalizedBodyMap(localizedBodyMap);
1351                    subscriptionSender.setLocalizedSubjectMap(localizedSubjectMap);
1352                    subscriptionSender.setMailId("blogs_entry", entry.getEntryId());
1353                    subscriptionSender.setPortletId(PortletKeys.BLOGS);
1354                    subscriptionSender.setReplyToAddress(fromAddress);
1355                    subscriptionSender.setScopeGroupId(entry.getGroupId());
1356                    subscriptionSender.setServiceContext(serviceContext);
1357                    subscriptionSender.setUserId(entry.getUserId());
1358    
1359                    subscriptionSender.addPersistedSubscribers(
1360                            BlogsEntry.class.getName(), entry.getGroupId());
1361    
1362                    subscriptionSender.flushNotificationsAsync();
1363            }
1364    
1365            protected void pingGoogle(BlogsEntry entry, ServiceContext serviceContext)
1366                    throws PortalException, SystemException {
1367    
1368                    if (!PropsValues.BLOGS_PING_GOOGLE_ENABLED || !entry.isApproved()) {
1369                            return;
1370                    }
1371    
1372                    String layoutFullURL = PortalUtil.getLayoutFullURL(
1373                            serviceContext.getScopeGroupId(), PortletKeys.BLOGS);
1374    
1375                    if (Validator.isNull(layoutFullURL)) {
1376                            return;
1377                    }
1378    
1379                    if (layoutFullURL.contains("://localhost")) {
1380                            if (_log.isDebugEnabled()) {
1381                                    _log.debug(
1382                                            "Not pinging Google because of localhost URL " +
1383                                                    layoutFullURL);
1384                            }
1385    
1386                            return;
1387                    }
1388    
1389                    Group group = groupPersistence.findByPrimaryKey(entry.getGroupId());
1390    
1391                    StringBundler sb = new StringBundler(6);
1392    
1393                    String name = group.getDescriptiveName();
1394                    String url = layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs";
1395                    String changesURL =
1396                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/rss";
1397    
1398                    sb.append("http://blogsearch.google.com/ping?name=");
1399                    sb.append(HttpUtil.encodeURL(name));
1400                    sb.append("&url=");
1401                    sb.append(HttpUtil.encodeURL(url));
1402                    sb.append("&changesURL=");
1403                    sb.append(HttpUtil.encodeURL(changesURL));
1404    
1405                    String location = sb.toString();
1406    
1407                    if (_log.isInfoEnabled()) {
1408                            _log.info("Pinging Google at " + location);
1409                    }
1410    
1411                    try {
1412                            String response = HttpUtil.URLtoString(sb.toString());
1413    
1414                            if (_log.isInfoEnabled()) {
1415                                    _log.info("Google ping response: " + response);
1416                            }
1417                    }
1418                    catch (IOException ioe) {
1419                            _log.error("Unable to ping Google at " + location, ioe);
1420                    }
1421            }
1422    
1423            protected void pingPingback(BlogsEntry entry, ServiceContext serviceContext)
1424                    throws PortalException, SystemException {
1425    
1426                    if (!PropsValues.BLOGS_PINGBACK_ENABLED ||
1427                            !entry.isAllowPingbacks() || !entry.isApproved()) {
1428    
1429                            return;
1430                    }
1431    
1432                    HttpServletRequest request = serviceContext.getRequest();
1433    
1434                    if (request == null) {
1435                            return;
1436                    }
1437    
1438                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
1439                            WebKeys.THEME_DISPLAY);
1440    
1441                    String layoutFullURL = PortalUtil.getLayoutFullURL(themeDisplay);
1442    
1443                    if (Validator.isNull(layoutFullURL)) {
1444                            return;
1445                    }
1446    
1447                    String sourceUri =
1448                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/" +
1449                                    entry.getUrlTitle();
1450    
1451                    Source source = new Source(entry.getContent());
1452    
1453                    List<StartTag> tags = source.getAllStartTags("a");
1454    
1455                    for (StartTag tag : tags) {
1456                            String targetUri = tag.getAttributeValue("href");
1457    
1458                            if (Validator.isNotNull(targetUri)) {
1459                                    try {
1460                                            LinkbackProducerUtil.sendPingback(sourceUri, targetUri);
1461                                    }
1462                                    catch (Exception e) {
1463                                            _log.error("Error while sending pingback " + targetUri, e);
1464                                    }
1465                            }
1466                    }
1467            }
1468    
1469            protected void pingTrackbacks(
1470                            BlogsEntry entry, String[] trackbacks, boolean pingOldTrackbacks,
1471                            ServiceContext serviceContext)
1472                    throws PortalException, SystemException {
1473    
1474                    if (!PropsValues.BLOGS_TRACKBACK_ENABLED ||
1475                            !entry.isAllowTrackbacks() || !entry.isApproved()) {
1476    
1477                            return;
1478                    }
1479    
1480                    HttpServletRequest request = serviceContext.getRequest();
1481    
1482                    if (request == null) {
1483                            return;
1484                    }
1485    
1486                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
1487                            WebKeys.THEME_DISPLAY);
1488    
1489                    String layoutFullURL = PortalUtil.getLayoutFullURL(themeDisplay);
1490    
1491                    if (Validator.isNull(layoutFullURL)) {
1492                            return;
1493                    }
1494    
1495                    Map<String, String> parts = new HashMap<String, String>();
1496    
1497                    String excerpt = StringUtil.shorten(
1498                            HtmlUtil.extractText(entry.getContent()),
1499                            PropsValues.BLOGS_LINKBACK_EXCERPT_LENGTH);
1500                    String url =
1501                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/" +
1502                                    entry.getUrlTitle();
1503    
1504                    parts.put("title", entry.getTitle());
1505                    parts.put("excerpt", excerpt);
1506                    parts.put("url", url);
1507                    parts.put("blog_name", entry.getUserName());
1508    
1509                    Set<String> trackbacksSet = null;
1510    
1511                    if (Validator.isNotNull(trackbacks)) {
1512                            trackbacksSet = SetUtil.fromArray(trackbacks);
1513                    }
1514                    else {
1515                            trackbacksSet = new HashSet<String>();
1516                    }
1517    
1518                    if (pingOldTrackbacks) {
1519                            trackbacksSet.addAll(
1520                                    SetUtil.fromArray(StringUtil.split(entry.getTrackbacks())));
1521    
1522                            entry.setTrackbacks(StringPool.BLANK);
1523    
1524                            blogsEntryPersistence.update(entry);
1525                    }
1526    
1527                    Set<String> oldTrackbacks = SetUtil.fromArray(
1528                            StringUtil.split(entry.getTrackbacks()));
1529    
1530                    Set<String> validTrackbacks = new HashSet<String>();
1531    
1532                    for (String trackback : trackbacksSet) {
1533                            if (oldTrackbacks.contains(trackback)) {
1534                                    continue;
1535                            }
1536    
1537                            try {
1538                                    if (LinkbackProducerUtil.sendTrackback(trackback, parts)) {
1539                                            validTrackbacks.add(trackback);
1540                                    }
1541                            }
1542                            catch (Exception e) {
1543                                    _log.error("Error while sending trackback at " + trackback, e);
1544                            }
1545                    }
1546    
1547                    if (!validTrackbacks.isEmpty()) {
1548                            String newTrackbacks = StringUtil.merge(validTrackbacks);
1549    
1550                            if (Validator.isNotNull(entry.getTrackbacks())) {
1551                                    newTrackbacks += StringPool.COMMA + entry.getTrackbacks();
1552                            }
1553    
1554                            entry.setTrackbacks(newTrackbacks);
1555    
1556                            blogsEntryPersistence.update(entry);
1557                    }
1558            }
1559    
1560            protected void saveImages(
1561                            boolean smallImage, long smallImageId, byte[] smallImageBytes)
1562                    throws PortalException, SystemException {
1563    
1564                    if (smallImage) {
1565                            if (smallImageBytes != null) {
1566                                    imageLocalService.updateImage(smallImageId, smallImageBytes);
1567                            }
1568                    }
1569                    else {
1570                            imageLocalService.deleteImage(smallImageId);
1571                    }
1572            }
1573    
1574            protected void validate(
1575                            String title, String content, boolean smallImage,
1576                            String smallImageURL, String smallImageFileName,
1577                            byte[] smallImageBytes)
1578                    throws PortalException, SystemException {
1579    
1580                    if (Validator.isNull(title)) {
1581                            throw new EntryTitleException();
1582                    }
1583                    else if (Validator.isNull(content)) {
1584                            throw new EntryContentException();
1585                    }
1586    
1587                    String[] imageExtensions = PrefsPropsUtil.getStringArray(
1588                            PropsKeys.BLOGS_IMAGE_EXTENSIONS, StringPool.COMMA);
1589    
1590                    if (smallImage && Validator.isNull(smallImageURL) &&
1591                            (smallImageBytes != null)) {
1592    
1593                            if (smallImageFileName != null) {
1594                                    boolean validSmallImageExtension = false;
1595    
1596                                    for (String _imageExtension : imageExtensions) {
1597                                            if (StringPool.STAR.equals(_imageExtension) ||
1598                                                    StringUtil.endsWith(
1599                                                            smallImageFileName, _imageExtension)) {
1600    
1601                                                    validSmallImageExtension = true;
1602    
1603                                                    break;
1604                                            }
1605                                    }
1606    
1607                                    if (!validSmallImageExtension) {
1608                                            throw new EntrySmallImageNameException(smallImageFileName);
1609                                    }
1610                            }
1611    
1612                            long smallImageMaxSize = PrefsPropsUtil.getLong(
1613                                    PropsKeys.BLOGS_IMAGE_SMALL_MAX_SIZE);
1614    
1615                            if ((smallImageMaxSize > 0) &&
1616                                    (smallImageBytes.length > smallImageMaxSize)) {
1617    
1618                                    throw new EntrySmallImageSizeException();
1619                            }
1620                    }
1621            }
1622    
1623            private static Log _log = LogFactoryUtil.getLog(
1624                    BlogsEntryLocalServiceImpl.class);
1625    
1626    }