001    /**
002     * Copyright (c) 2000-present 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.bean.BeanReference;
018    import com.liferay.portal.kernel.comment.CommentManager;
019    import com.liferay.portal.kernel.dao.orm.QueryDefinition;
020    import com.liferay.portal.kernel.exception.PortalException;
021    import com.liferay.portal.kernel.json.JSONFactoryUtil;
022    import com.liferay.portal.kernel.json.JSONObject;
023    import com.liferay.portal.kernel.log.Log;
024    import com.liferay.portal.kernel.log.LogFactoryUtil;
025    import com.liferay.portal.kernel.notifications.UserNotificationDefinition;
026    import com.liferay.portal.kernel.repository.model.FileEntry;
027    import com.liferay.portal.kernel.repository.model.Folder;
028    import com.liferay.portal.kernel.search.Indexable;
029    import com.liferay.portal.kernel.search.IndexableType;
030    import com.liferay.portal.kernel.search.Indexer;
031    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
032    import com.liferay.portal.kernel.servlet.taglib.ui.ImageSelector;
033    import com.liferay.portal.kernel.settings.LocalizedValuesMap;
034    import com.liferay.portal.kernel.systemevent.SystemEvent;
035    import com.liferay.portal.kernel.util.ArrayUtil;
036    import com.liferay.portal.kernel.util.Constants;
037    import com.liferay.portal.kernel.util.ContentTypes;
038    import com.liferay.portal.kernel.util.FileUtil;
039    import com.liferay.portal.kernel.util.GetterUtil;
040    import com.liferay.portal.kernel.util.HtmlUtil;
041    import com.liferay.portal.kernel.util.HttpUtil;
042    import com.liferay.portal.kernel.util.LocalizationUtil;
043    import com.liferay.portal.kernel.util.MimeTypesUtil;
044    import com.liferay.portal.kernel.util.OrderByComparator;
045    import com.liferay.portal.kernel.util.ParamUtil;
046    import com.liferay.portal.kernel.util.PropsKeys;
047    import com.liferay.portal.kernel.util.SetUtil;
048    import com.liferay.portal.kernel.util.StringBundler;
049    import com.liferay.portal.kernel.util.StringPool;
050    import com.liferay.portal.kernel.util.StringUtil;
051    import com.liferay.portal.kernel.util.TempFileEntryUtil;
052    import com.liferay.portal.kernel.util.Time;
053    import com.liferay.portal.kernel.util.Validator;
054    import com.liferay.portal.kernel.util.WebKeys;
055    import com.liferay.portal.kernel.workflow.WorkflowConstants;
056    import com.liferay.portal.kernel.workflow.WorkflowHandlerRegistryUtil;
057    import com.liferay.portal.model.Group;
058    import com.liferay.portal.model.ModelHintsUtil;
059    import com.liferay.portal.model.Repository;
060    import com.liferay.portal.model.ResourceConstants;
061    import com.liferay.portal.model.SystemEventConstants;
062    import com.liferay.portal.model.User;
063    import com.liferay.portal.portletfilerepository.PortletFileRepositoryUtil;
064    import com.liferay.portal.service.ServiceContext;
065    import com.liferay.portal.theme.ThemeDisplay;
066    import com.liferay.portal.util.GroupSubscriptionCheckSubscriptionSender;
067    import com.liferay.portal.util.LayoutURLUtil;
068    import com.liferay.portal.util.Portal;
069    import com.liferay.portal.util.PortalUtil;
070    import com.liferay.portal.util.PortletKeys;
071    import com.liferay.portal.util.PrefsPropsUtil;
072    import com.liferay.portal.util.PropsValues;
073    import com.liferay.portal.util.SubscriptionSender;
074    import com.liferay.portlet.PortletURLFactoryUtil;
075    import com.liferay.portlet.asset.model.AssetEntry;
076    import com.liferay.portlet.asset.model.AssetLinkConstants;
077    import com.liferay.portlet.blogs.BlogsGroupServiceSettings;
078    import com.liferay.portlet.blogs.EntryContentException;
079    import com.liferay.portlet.blogs.EntryDisplayDateException;
080    import com.liferay.portlet.blogs.EntrySmallImageNameException;
081    import com.liferay.portlet.blogs.EntrySmallImageSizeException;
082    import com.liferay.portlet.blogs.EntryTitleException;
083    import com.liferay.portlet.blogs.model.BlogsEntry;
084    import com.liferay.portlet.blogs.service.base.BlogsEntryLocalServiceBaseImpl;
085    import com.liferay.portlet.blogs.service.permission.BlogsPermission;
086    import com.liferay.portlet.blogs.social.BlogsActivityKeys;
087    import com.liferay.portlet.blogs.util.BlogsUtil;
088    import com.liferay.portlet.blogs.util.LinkbackProducerUtil;
089    import com.liferay.portlet.blogs.util.comparator.EntryDisplayDateComparator;
090    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
091    import com.liferay.portlet.social.model.SocialActivityConstants;
092    import com.liferay.portlet.trash.model.TrashEntry;
093    
094    import java.io.File;
095    import java.io.IOException;
096    import java.io.InputStream;
097    import java.io.Serializable;
098    
099    import java.util.Date;
100    import java.util.HashMap;
101    import java.util.HashSet;
102    import java.util.List;
103    import java.util.Map;
104    import java.util.Set;
105    
106    import javax.portlet.PortletRequest;
107    import javax.portlet.PortletURL;
108    
109    import javax.servlet.http.HttpServletRequest;
110    
111    import net.htmlparser.jericho.Source;
112    import net.htmlparser.jericho.StartTag;
113    
114    /**
115     * Provides the local service for accessing, adding, checking, deleting,
116     * subscription handling of, trash handling of, and updating blog entries.
117     *
118     * @author Brian Wing Shun Chan
119     * @author Wilson S. Man
120     * @author Raymond Aug??
121     * @author Thiago Moreira
122     * @author Juan Fern??ndez
123     * @author Zsolt Berentey
124     */
125    public class BlogsEntryLocalServiceImpl extends BlogsEntryLocalServiceBaseImpl {
126    
127            @Override
128            public Folder addAttachmentsFolder(long userId, long groupId)
129                    throws PortalException {
130    
131                    ServiceContext serviceContext = new ServiceContext();
132    
133                    serviceContext.setAddGroupPermissions(true);
134                    serviceContext.setAddGuestPermissions(true);
135    
136                    Repository repository = PortletFileRepositoryUtil.addPortletRepository(
137                            groupId, PortletKeys.BLOGS, serviceContext);
138    
139                    Folder folder = PortletFileRepositoryUtil.addPortletFolder(
140                            userId, repository.getRepositoryId(),
141                            DLFolderConstants.DEFAULT_PARENT_FOLDER_ID, PortletKeys.BLOGS,
142                            serviceContext);
143    
144                    return folder;
145            }
146    
147            @Override
148            public BlogsEntry addEntry(
149                            long userId, String title, String content, Date displayDate,
150                            ServiceContext serviceContext)
151                    throws PortalException {
152    
153                    return addEntry(
154                            userId, title, StringPool.BLANK, StringPool.BLANK, content,
155                            displayDate, true, true, new String[0], StringPool.BLANK, null,
156                            null, serviceContext);
157            }
158    
159            @Override
160            public BlogsEntry addEntry(
161                            long userId, String title, String content,
162                            ServiceContext serviceContext)
163                    throws PortalException {
164    
165                    return addEntry(
166                            userId, title, StringPool.BLANK, StringPool.BLANK, content,
167                            new Date(), true, true, new String[0], StringPool.BLANK, null, null,
168                            serviceContext);
169            }
170    
171            /**
172             * @deprecated As of 7.0.0, replaced by {@link #addEntry(long, String,
173             *             String, String, String, int, int, int, int, int, boolean,
174             *             boolean, String[], String, ImageSelector, ImageSelector,
175             *             ServiceContext)}
176             */
177            @Deprecated
178            @Override
179            public BlogsEntry addEntry(
180                            long userId, String title, String description, String content,
181                            int displayDateMonth, int displayDateDay, int displayDateYear,
182                            int displayDateHour, int displayDateMinute, boolean allowPingbacks,
183                            boolean allowTrackbacks, String[] trackbacks, boolean smallImage,
184                            String smallImageURL, String smallImageFileName,
185                            InputStream smallImageInputStream, ServiceContext serviceContext)
186                    throws PortalException {
187    
188                    ImageSelector coverImageImageSelector = null;
189                    ImageSelector smallImageImageSelector = null;
190    
191                    if (smallImage && Validator.isNotNull(smallImageFileName) &&
192                            (smallImageInputStream != null)) {
193    
194                            FileEntry tempFileEntry = TempFileEntryUtil.addTempFileEntry(
195                                    serviceContext.getScopeGroupId(), userId,
196                                    BlogsEntry.class.getName(), smallImageFileName,
197                                    smallImageInputStream,
198                                    MimeTypesUtil.getContentType(smallImageFileName));
199    
200                            smallImageImageSelector = new ImageSelector(
201                                    tempFileEntry.getFileEntryId(), smallImageURL, null);
202                    }
203    
204                    return addEntry(
205                            userId, title, StringPool.BLANK, description, content,
206                            displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
207                            displayDateMinute, allowPingbacks, allowTrackbacks, trackbacks,
208                            StringPool.BLANK, coverImageImageSelector, smallImageImageSelector,
209                            serviceContext);
210            }
211    
212            @Indexable(type = IndexableType.REINDEX)
213            @Override
214            public BlogsEntry addEntry(
215                            long userId, String title, String subtitle, String description,
216                            String content, Date displayDate, boolean allowPingbacks,
217                            boolean allowTrackbacks, String[] trackbacks,
218                            String coverImageCaption, ImageSelector coverImageImageSelector,
219                            ImageSelector smallImageImageSelector,
220                            ServiceContext serviceContext)
221                    throws PortalException {
222    
223                    // Entry
224    
225                    User user = userPersistence.findByPrimaryKey(userId);
226                    long groupId = serviceContext.getScopeGroupId();
227    
228                    long entryId = counterLocalService.increment();
229    
230                    validate(title, content);
231    
232                    BlogsEntry entry = blogsEntryPersistence.create(entryId);
233    
234                    entry.setUuid(serviceContext.getUuid());
235                    entry.setGroupId(groupId);
236                    entry.setCompanyId(user.getCompanyId());
237                    entry.setUserId(user.getUserId());
238                    entry.setUserName(user.getFullName());
239                    entry.setTitle(title);
240                    entry.setSubtitle(subtitle);
241                    entry.setUrlTitle(
242                            getUniqueUrlTitle(entryId, title, null, serviceContext));
243                    entry.setDescription(description);
244                    entry.setContent(content);
245                    entry.setDisplayDate(displayDate);
246                    entry.setAllowPingbacks(allowPingbacks);
247                    entry.setAllowTrackbacks(allowTrackbacks);
248                    entry.setStatus(WorkflowConstants.STATUS_DRAFT);
249                    entry.setStatusByUserId(userId);
250                    entry.setStatusDate(serviceContext.getModifiedDate(null));
251                    entry.setExpandoBridgeAttributes(serviceContext);
252    
253                    blogsEntryPersistence.update(entry);
254    
255                    // Resources
256    
257                    if (serviceContext.isAddGroupPermissions() ||
258                            serviceContext.isAddGuestPermissions()) {
259    
260                            addEntryResources(
261                                    entry, serviceContext.isAddGroupPermissions(),
262                                    serviceContext.isAddGuestPermissions());
263                    }
264                    else {
265                            addEntryResources(
266                                    entry, serviceContext.getGroupPermissions(),
267                                    serviceContext.getGuestPermissions());
268                    }
269    
270                    // Asset
271    
272                    updateAsset(
273                            userId, entry, serviceContext.getAssetCategoryIds(),
274                            serviceContext.getAssetTagNames(),
275                            serviceContext.getAssetLinkEntryIds());
276    
277                    // Comment
278    
279                    addDiscussion(entry, userId, groupId);
280    
281                    // Images
282    
283                    long coverImageFileEntryId = 0;
284                    String coverImageURL = null;
285    
286                    if (coverImageImageSelector != null) {
287                            coverImageFileEntryId = coverImageImageSelector.getImageId();
288                            coverImageURL = coverImageImageSelector.getImageURL();
289                    }
290    
291                    if (coverImageFileEntryId != 0) {
292                            coverImageFileEntryId = addCoverImage(
293                                    userId, groupId, entryId, coverImageImageSelector);
294                    }
295    
296                    boolean smallImage = false;
297                    long smallImageFileEntryId = 0;
298                    String smallImageURL = null;
299    
300                    if (smallImageImageSelector != null) {
301                            smallImage = !smallImageImageSelector.isRemoveSmallImage();
302                            smallImageFileEntryId = smallImageImageSelector.getImageId();
303                            smallImageURL = smallImageImageSelector.getImageURL();
304                    }
305    
306                    FileEntry tempSmallImageFileEntry = null;
307    
308                    if (smallImageFileEntryId != 0) {
309                            tempSmallImageFileEntry =
310                                    PortletFileRepositoryUtil.getPortletFileEntry(
311                                            smallImageFileEntryId);
312    
313                            smallImageFileEntryId = addSmallImageFileEntry(
314                                    userId, groupId, entryId, tempSmallImageFileEntry.getMimeType(),
315                                    tempSmallImageFileEntry.getTitle(),
316                                    tempSmallImageFileEntry.getContentStream());
317                    }
318    
319                    validate(smallImageFileEntryId);
320    
321                    entry.setCoverImageCaption(coverImageCaption);
322                    entry.setCoverImageFileEntryId(coverImageFileEntryId);
323                    entry.setCoverImageURL(coverImageURL);
324                    entry.setSmallImage(smallImage);
325                    entry.setSmallImageFileEntryId(smallImageFileEntryId);
326                    entry.setSmallImageURL(smallImageURL);
327    
328                    blogsEntryPersistence.update(entry);
329    
330                    // Workflow
331    
332                    if (ArrayUtil.isNotEmpty(trackbacks)) {
333                            serviceContext.setAttribute("trackbacks", trackbacks);
334                    }
335                    else {
336                            serviceContext.setAttribute("trackbacks", null);
337                    }
338    
339                    entry = startWorkflowInstance(userId, entry, serviceContext);
340    
341                    if ((coverImageImageSelector != null) &&
342                            (coverImageImageSelector.getImageId() != 0)) {
343    
344                            PortletFileRepositoryUtil.deletePortletFileEntry(
345                                    coverImageImageSelector.getImageId());
346                    }
347    
348                    if (tempSmallImageFileEntry != null) {
349                            PortletFileRepositoryUtil.deletePortletFileEntry(
350                                    tempSmallImageFileEntry.getFileEntryId());
351                    }
352    
353                    return entry;
354            }
355    
356            @Override
357            public BlogsEntry addEntry(
358                            long userId, String title, String subtitle, String description,
359                            String content, int displayDateMonth, int displayDateDay,
360                            int displayDateYear, int displayDateHour, int displayDateMinute,
361                            boolean allowPingbacks, boolean allowTrackbacks,
362                            String[] trackbacks, String coverImageCaption,
363                            ImageSelector coverImageImageSelector,
364                            ImageSelector smallImageImageSelector,
365                            ServiceContext serviceContext)
366                    throws PortalException {
367    
368                    User user = userPersistence.findByPrimaryKey(userId);
369    
370                    Date displayDate = PortalUtil.getDate(
371                            displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
372                            displayDateMinute, user.getTimeZone(),
373                            EntryDisplayDateException.class);
374    
375                    return addEntry(
376                            userId, title, subtitle, description, content, displayDate,
377                            allowPingbacks, allowTrackbacks, trackbacks, coverImageCaption,
378                            coverImageImageSelector, smallImageImageSelector, serviceContext);
379            }
380    
381            @Override
382            public void addEntryResources(
383                            BlogsEntry entry, boolean addGroupPermissions,
384                            boolean addGuestPermissions)
385                    throws PortalException {
386    
387                    resourceLocalService.addResources(
388                            entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
389                            BlogsEntry.class.getName(), entry.getEntryId(), false,
390                            addGroupPermissions, addGuestPermissions);
391            }
392    
393            @Override
394            public void addEntryResources(
395                            BlogsEntry entry, String[] groupPermissions,
396                            String[] guestPermissions)
397                    throws PortalException {
398    
399                    resourceLocalService.addModelResources(
400                            entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
401                            BlogsEntry.class.getName(), entry.getEntryId(), groupPermissions,
402                            guestPermissions);
403            }
404    
405            @Override
406            public void addEntryResources(
407                            long entryId, boolean addGroupPermissions,
408                            boolean addGuestPermissions)
409                    throws PortalException {
410    
411                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
412    
413                    addEntryResources(entry, addGroupPermissions, addGuestPermissions);
414            }
415    
416            @Override
417            public void addEntryResources(
418                            long entryId, String[] groupPermissions, String[] guestPermissions)
419                    throws PortalException {
420    
421                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
422    
423                    addEntryResources(entry, groupPermissions, guestPermissions);
424            }
425    
426            @Override
427            public void checkEntries() throws PortalException {
428                    Date now = new Date();
429    
430                    int count = blogsEntryPersistence.countByLtD_S(
431                            now, WorkflowConstants.STATUS_SCHEDULED);
432    
433                    if (count == 0) {
434                            return;
435                    }
436    
437                    List<BlogsEntry> entries = blogsEntryPersistence.findByLtD_S(
438                            now, WorkflowConstants.STATUS_SCHEDULED);
439    
440                    for (BlogsEntry entry : entries) {
441                            ServiceContext serviceContext = new ServiceContext();
442    
443                            String[] trackbacks = StringUtil.split(entry.getTrackbacks());
444    
445                            serviceContext.setAttribute("trackbacks", trackbacks);
446    
447                            serviceContext.setCommand(Constants.UPDATE);
448    
449                            String layoutFullURL = PortalUtil.getLayoutFullURL(
450                                    entry.getGroupId(), PortletKeys.BLOGS);
451    
452                            serviceContext.setLayoutFullURL(layoutFullURL);
453    
454                            serviceContext.setScopeGroupId(entry.getGroupId());
455    
456                            blogsEntryLocalService.updateStatus(
457                                    entry.getStatusByUserId(), entry.getEntryId(),
458                                    WorkflowConstants.STATUS_APPROVED, serviceContext,
459                                    new HashMap<String, Serializable>());
460                    }
461            }
462    
463            @Override
464            public void deleteEntries(long groupId) throws PortalException {
465                    for (BlogsEntry entry : blogsEntryPersistence.findByGroupId(groupId)) {
466                            blogsEntryLocalService.deleteEntry(entry);
467                    }
468            }
469    
470            @Indexable(type = IndexableType.DELETE)
471            @Override
472            @SystemEvent(type = SystemEventConstants.TYPE_DELETE)
473            public BlogsEntry deleteEntry(BlogsEntry entry) throws PortalException {
474    
475                    // Entry
476    
477                    blogsEntryPersistence.remove(entry);
478    
479                    // Resources
480    
481                    resourceLocalService.deleteResource(
482                            entry.getCompanyId(), BlogsEntry.class.getName(),
483                            ResourceConstants.SCOPE_INDIVIDUAL, entry.getEntryId());
484    
485                    // Image
486    
487                    imageLocalService.deleteImage(entry.getSmallImageId());
488    
489                    // Subscriptions
490    
491                    subscriptionLocalService.deleteSubscriptions(
492                            entry.getCompanyId(), BlogsEntry.class.getName(),
493                            entry.getEntryId());
494    
495                    // Statistics
496    
497                    blogsStatsUserLocalService.updateStatsUser(
498                            entry.getGroupId(), entry.getUserId(), entry.getDisplayDate());
499    
500                    // Asset
501    
502                    assetEntryLocalService.deleteEntry(
503                            BlogsEntry.class.getName(), entry.getEntryId());
504    
505                    // Comment
506    
507                    deleteDiscussion(entry);
508    
509                    // Expando
510    
511                    expandoRowLocalService.deleteRows(entry.getEntryId());
512    
513                    // Ratings
514    
515                    ratingsStatsLocalService.deleteStats(
516                            BlogsEntry.class.getName(), entry.getEntryId());
517    
518                    // Trash
519    
520                    trashEntryLocalService.deleteEntry(
521                            BlogsEntry.class.getName(), entry.getEntryId());
522    
523                    // Indexer
524    
525                    Indexer indexer = IndexerRegistryUtil.nullSafeGetIndexer(
526                            BlogsEntry.class);
527    
528                    indexer.delete(entry);
529    
530                    // Workflow
531    
532                    workflowInstanceLinkLocalService.deleteWorkflowInstanceLinks(
533                            entry.getCompanyId(), entry.getGroupId(),
534                            BlogsEntry.class.getName(), entry.getEntryId());
535    
536                    return entry;
537            }
538    
539            @Override
540            public void deleteEntry(long entryId) throws PortalException {
541                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
542    
543                    blogsEntryLocalService.deleteEntry(entry);
544            }
545    
546            @Override
547            public Folder fetchAttachmentsFolder(long userId, long groupId) {
548                    ServiceContext serviceContext = new ServiceContext();
549    
550                    serviceContext.setAddGroupPermissions(true);
551                    serviceContext.setAddGuestPermissions(true);
552    
553                    Repository repository =
554                            PortletFileRepositoryUtil.fetchPortletRepository(
555                                    groupId, PortletKeys.BLOGS);
556    
557                    try {
558                            Folder folder = PortletFileRepositoryUtil.getPortletFolder(
559                                    repository.getRepositoryId(),
560                                    DLFolderConstants.DEFAULT_PARENT_FOLDER_ID, PortletKeys.BLOGS);
561    
562                            return folder;
563                    }
564                    catch (Exception e) {
565                    }
566    
567                    return null;
568            }
569    
570            /**
571             * @deprecated As of 6.2.0, replaced by {@link #getCompanyEntries(long,
572             *             Date, QueryDefinition)}
573             */
574            @Deprecated
575            @Override
576            public List<BlogsEntry> getCompanyEntries(
577                    long companyId, Date displayDate, int status, int start, int end) {
578    
579                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
580                            status, start, end, null);
581    
582                    return getCompanyEntries(companyId, displayDate, queryDefinition);
583            }
584    
585            /**
586             * @deprecated As of 6.2.0, replaced by {@link #getCompanyEntries(long,
587             *             Date, QueryDefinition)}
588             */
589            @Deprecated
590            @Override
591            public List<BlogsEntry> getCompanyEntries(
592                    long companyId, Date displayDate, int status, int start, int end,
593                    OrderByComparator<BlogsEntry> obc) {
594    
595                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
596                            status, start, end, obc);
597    
598                    return getCompanyEntries(companyId, displayDate, queryDefinition);
599            }
600    
601            @Override
602            public List<BlogsEntry> getCompanyEntries(
603                    long companyId, Date displayDate,
604                    QueryDefinition<BlogsEntry> queryDefinition) {
605    
606                    if (queryDefinition.isExcludeStatus()) {
607                            return blogsEntryPersistence.findByC_LtD_NotS(
608                                    companyId, displayDate, queryDefinition.getStatus(),
609                                    queryDefinition.getStart(), queryDefinition.getEnd(),
610                                    queryDefinition.getOrderByComparator());
611                    }
612                    else {
613                            return blogsEntryPersistence.findByC_LtD_S(
614                                    companyId, displayDate, queryDefinition.getStatus(),
615                                    queryDefinition.getStart(), queryDefinition.getEnd(),
616                                    queryDefinition.getOrderByComparator());
617                    }
618            }
619    
620            /**
621             * @deprecated As of 6.2.0, replaced by {@link #getCompanyEntriesCount(long,
622             *             Date, QueryDefinition)}
623             */
624            @Deprecated
625            @Override
626            public int getCompanyEntriesCount(
627                    long companyId, Date displayDate, int status) {
628    
629                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
630                            status);
631    
632                    return getCompanyEntriesCount(companyId, displayDate, queryDefinition);
633            }
634    
635            @Override
636            public int getCompanyEntriesCount(
637                    long companyId, Date displayDate,
638                    QueryDefinition<BlogsEntry> queryDefinition) {
639    
640                    if (queryDefinition.isExcludeStatus()) {
641                            return blogsEntryPersistence.countByC_LtD_NotS(
642                                    companyId, displayDate, queryDefinition.getStatus());
643                    }
644                    else {
645                            return blogsEntryPersistence.countByC_LtD_S(
646                                    companyId, displayDate, queryDefinition.getStatus());
647                    }
648            }
649    
650            @Override
651            public BlogsEntry[] getEntriesPrevAndNext(long entryId)
652                    throws PortalException {
653    
654                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
655    
656                    return blogsEntryPersistence.findByG_S_PrevAndNext(
657                            entry.getEntryId(), entry.getGroupId(),
658                            WorkflowConstants.STATUS_APPROVED,
659                            new EntryDisplayDateComparator(true));
660            }
661    
662            @Override
663            public BlogsEntry getEntry(long entryId) throws PortalException {
664                    return blogsEntryPersistence.findByPrimaryKey(entryId);
665            }
666    
667            @Override
668            public BlogsEntry getEntry(long groupId, String urlTitle)
669                    throws PortalException {
670    
671                    return blogsEntryPersistence.findByG_UT(groupId, urlTitle);
672            }
673    
674            /**
675             * @deprecated As of 6.2.0, replaced by {@link #getGroupEntries(long, Date,
676             *             QueryDefinition)}
677             */
678            @Deprecated
679            @Override
680            public List<BlogsEntry> getGroupEntries(
681                    long groupId, Date displayDate, int status, int start, int end) {
682    
683                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
684                            status, start, end, null);
685    
686                    return getGroupEntries(groupId, displayDate, queryDefinition);
687            }
688    
689            /**
690             * @deprecated As of 6.2.0, replaced by {@link #getGroupEntries(long, Date,
691             *             QueryDefinition)}
692             */
693            @Deprecated
694            @Override
695            public List<BlogsEntry> getGroupEntries(
696                    long groupId, Date displayDate, int status, int start, int end,
697                    OrderByComparator<BlogsEntry> obc) {
698    
699                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
700                            status, start, end, obc);
701    
702                    return getGroupEntries(groupId, displayDate, queryDefinition);
703            }
704    
705            @Override
706            public List<BlogsEntry> getGroupEntries(
707                    long groupId, Date displayDate,
708                    QueryDefinition<BlogsEntry> queryDefinition) {
709    
710                    if (queryDefinition.isExcludeStatus()) {
711                            return blogsEntryPersistence.findByG_LtD_NotS(
712                                    groupId, displayDate, queryDefinition.getStatus(),
713                                    queryDefinition.getStart(), queryDefinition.getEnd(),
714                                    queryDefinition.getOrderByComparator());
715                    }
716                    else {
717                            return blogsEntryPersistence.findByG_LtD_S(
718                                    groupId, displayDate, queryDefinition.getStatus(),
719                                    queryDefinition.getStart(), queryDefinition.getEnd(),
720                                    queryDefinition.getOrderByComparator());
721                    }
722            }
723    
724            /**
725             * @deprecated As of 6.2.0, replaced by {@link #getGroupEntries(long,
726             *             QueryDefinition)}
727             */
728            @Deprecated
729            @Override
730            public List<BlogsEntry> getGroupEntries(
731                    long groupId, int status, int start, int end) {
732    
733                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
734                            status, start, end, null);
735    
736                    return getGroupEntries(groupId, queryDefinition);
737            }
738    
739            /**
740             * @deprecated As of 6.2.0, replaced by {@link #getGroupEntries(long,
741             *             QueryDefinition)}
742             */
743            @Deprecated
744            @Override
745            public List<BlogsEntry> getGroupEntries(
746                    long groupId, int status, int start, int end,
747                    OrderByComparator<BlogsEntry> obc) {
748    
749                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
750                            status, start, end, obc);
751    
752                    return getGroupEntries(groupId, queryDefinition);
753            }
754    
755            @Override
756            public List<BlogsEntry> getGroupEntries(
757                    long groupId, QueryDefinition<BlogsEntry> queryDefinition) {
758    
759                    if (queryDefinition.isExcludeStatus()) {
760                            return blogsEntryPersistence.findByG_NotS(
761                                    groupId, queryDefinition.getStatus(),
762                                    queryDefinition.getStart(), queryDefinition.getEnd(),
763                                    queryDefinition.getOrderByComparator());
764                    }
765                    else {
766                            return blogsEntryPersistence.findByG_S(
767                                    groupId, queryDefinition.getStatus(),
768                                    queryDefinition.getStart(), queryDefinition.getEnd(),
769                                    queryDefinition.getOrderByComparator());
770                    }
771            }
772    
773            /**
774             * @deprecated As of 6.2.0, replaced by {@link #getGroupEntriesCount(long,
775             *             Date, QueryDefinition)}
776             */
777            @Deprecated
778            @Override
779            public int getGroupEntriesCount(
780                    long groupId, Date displayDate, int status) {
781    
782                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
783                            status);
784    
785                    return getGroupEntriesCount(groupId, displayDate, queryDefinition);
786            }
787    
788            @Override
789            public int getGroupEntriesCount(
790                    long groupId, Date displayDate,
791                    QueryDefinition<BlogsEntry> queryDefinition) {
792    
793                    if (queryDefinition.isExcludeStatus()) {
794                            return blogsEntryPersistence.countByG_LtD_NotS(
795                                    groupId, displayDate, queryDefinition.getStatus());
796                    }
797                    else {
798                            return blogsEntryPersistence.countByG_LtD_S(
799                                    groupId, displayDate, queryDefinition.getStatus());
800                    }
801            }
802    
803            /**
804             * @deprecated As of 6.2.0, replaced by {@link #getGroupEntriesCount(long,
805             *             QueryDefinition)}
806             */
807            @Deprecated
808            @Override
809            public int getGroupEntriesCount(long groupId, int status) {
810                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
811                            status);
812    
813                    return getGroupEntriesCount(groupId, queryDefinition);
814            }
815    
816            @Override
817            public int getGroupEntriesCount(
818                    long groupId, QueryDefinition<BlogsEntry> queryDefinition) {
819    
820                    if (queryDefinition.isExcludeStatus()) {
821                            return blogsEntryPersistence.countByG_NotS(
822                                    groupId, queryDefinition.getStatus());
823                    }
824                    else {
825                            return blogsEntryPersistence.countByG_S(
826                                    groupId, queryDefinition.getStatus());
827                    }
828            }
829    
830            /**
831             * @deprecated As of 6.2.0, replaced by {@link #getGroupsEntries(long, long,
832             *             Date, QueryDefinition)}
833             */
834            @Deprecated
835            @Override
836            public List<BlogsEntry> getGroupsEntries(
837                    long companyId, long groupId, Date displayDate, int status, int start,
838                    int end) {
839    
840                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
841                            status, start, end, null);
842    
843                    return getGroupsEntries(
844                            companyId, groupId, displayDate, queryDefinition);
845            }
846    
847            @Override
848            public List<BlogsEntry> getGroupsEntries(
849                    long companyId, long groupId, Date displayDate,
850                    QueryDefinition<BlogsEntry> queryDefinition) {
851    
852                    return blogsEntryFinder.findByGroupIds(
853                            companyId, groupId, displayDate, queryDefinition);
854            }
855    
856            /**
857             * @deprecated As of 6.2.0, replaced by {@link #getGroupUserEntries(long,
858             *             long, Date, QueryDefinition)}
859             */
860            @Deprecated
861            @Override
862            public List<BlogsEntry> getGroupUserEntries(
863                    long groupId, long userId, Date displayDate, int status, int start,
864                    int end) {
865    
866                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
867                            status, start, end, null);
868    
869                    return getGroupUserEntries(
870                            groupId, userId, displayDate, queryDefinition);
871            }
872    
873            /**
874             * @deprecated As of 6.2.0, replaced by {@link #getGroupUserEntries(long,
875             *             long, Date, QueryDefinition)}
876             */
877            @Deprecated
878            @Override
879            public List<BlogsEntry> getGroupUserEntries(
880                    long groupId, long userId, Date displayDate, int status, int start,
881                    int end, OrderByComparator<BlogsEntry> obc) {
882    
883                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
884                            status, start, end, obc);
885    
886                    return getGroupUserEntries(
887                            groupId, userId, displayDate, queryDefinition);
888            }
889    
890            @Override
891            public List<BlogsEntry> getGroupUserEntries(
892                    long groupId, long userId, Date displayDate,
893                    QueryDefinition<BlogsEntry> queryDefinition) {
894    
895                    if (queryDefinition.isExcludeStatus()) {
896                            return blogsEntryPersistence.findByG_U_NotS(
897                                    groupId, userId, queryDefinition.getStatus(),
898                                    queryDefinition.getStart(), queryDefinition.getEnd(),
899                                    queryDefinition.getOrderByComparator());
900                    }
901                    else {
902                            return blogsEntryPersistence.findByG_U_S(
903                                    groupId, userId, queryDefinition.getStatus(),
904                                    queryDefinition.getStart(), queryDefinition.getEnd(),
905                                    queryDefinition.getOrderByComparator());
906                    }
907            }
908    
909            /**
910             * @deprecated As of 6.2.0, replaced by {@link
911             *             #getGroupUserEntriesCount(long, long, Date, QueryDefinition)}
912             */
913            @Deprecated
914            @Override
915            public int getGroupUserEntriesCount(
916                    long groupId, long userId, Date displayDate, int status) {
917    
918                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
919                            status);
920    
921                    return getGroupUserEntriesCount(
922                            groupId, userId, displayDate, queryDefinition);
923            }
924    
925            @Override
926            public int getGroupUserEntriesCount(
927                    long groupId, long userId, Date displayDate,
928                    QueryDefinition<BlogsEntry> queryDefinition) {
929    
930                    if (queryDefinition.isExcludeStatus()) {
931                            return blogsEntryPersistence.countByG_U_LtD_NotS(
932                                    groupId, userId, displayDate, queryDefinition.getStatus());
933                    }
934                    else {
935                            return blogsEntryPersistence.countByG_U_LtD_S(
936                                    groupId, userId, displayDate, queryDefinition.getStatus());
937                    }
938            }
939    
940            @Override
941            public List<BlogsEntry> getNoAssetEntries() {
942                    return blogsEntryFinder.findByNoAssets();
943            }
944    
945            /**
946             * @deprecated As of 6.2.0, replaced by {@link #getOrganizationEntries(long,
947             *             Date, QueryDefinition)}
948             */
949            @Deprecated
950            @Override
951            public List<BlogsEntry> getOrganizationEntries(
952                    long organizationId, Date displayDate, int status, int start, int end) {
953    
954                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
955                            status, start, end, null);
956    
957                    return getOrganizationEntries(
958                            organizationId, displayDate, queryDefinition);
959            }
960    
961            /**
962             * @deprecated As of 6.2.0, replaced by {@link #getOrganizationEntries(long,
963             *             Date, QueryDefinition)}
964             */
965            @Deprecated
966            @Override
967            public List<BlogsEntry> getOrganizationEntries(
968                    long organizationId, Date displayDate, int status, int start, int end,
969                    OrderByComparator<BlogsEntry> obc) {
970    
971                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
972                            status, start, end, obc);
973    
974                    return getOrganizationEntries(
975                            organizationId, displayDate, queryDefinition);
976            }
977    
978            @Override
979            public List<BlogsEntry> getOrganizationEntries(
980                    long organizationId, Date displayDate,
981                    QueryDefinition<BlogsEntry> queryDefinition) {
982    
983                    return blogsEntryFinder.findByOrganizationId(
984                            organizationId, displayDate, queryDefinition);
985            }
986    
987            /**
988             * @deprecated As of 6.2.0, replaced by {@link
989             *             #getOrganizationEntriesCount(long, Date, QueryDefinition)}
990             */
991            @Deprecated
992            @Override
993            public int getOrganizationEntriesCount(
994                    long organizationId, Date displayDate, int status) {
995    
996                    QueryDefinition<BlogsEntry> queryDefinition = new QueryDefinition<>(
997                            status);
998    
999                    return getOrganizationEntriesCount(
1000                            organizationId, displayDate, queryDefinition);
1001            }
1002    
1003            @Override
1004            public int getOrganizationEntriesCount(
1005                    long organizationId, Date displayDate,
1006                    QueryDefinition<BlogsEntry> queryDefinition) {
1007    
1008                    return blogsEntryFinder.countByOrganizationId(
1009                            organizationId, displayDate, queryDefinition);
1010            }
1011    
1012            @Override
1013            public void moveEntriesToTrash(long groupId, long userId)
1014                    throws PortalException {
1015    
1016                    List<BlogsEntry> entries = blogsEntryPersistence.findByGroupId(groupId);
1017    
1018                    for (BlogsEntry entry : entries) {
1019                            blogsEntryLocalService.moveEntryToTrash(userId, entry);
1020                    }
1021            }
1022    
1023            /**
1024             * Moves the blogs entry to the recycle bin. Social activity counters for
1025             * this entry get disabled.
1026             *
1027             * @param  userId the primary key of the user moving the blogs entry
1028             * @param  entry the blogs entry to be moved
1029             * @return the moved blogs entry
1030             * @throws PortalException if a user with the primary key could not be found
1031             *         or if the blogs entry owner's social activity counter could not
1032             *         be updated
1033             */
1034            @Indexable(type = IndexableType.REINDEX)
1035            @Override
1036            public BlogsEntry moveEntryToTrash(long userId, BlogsEntry entry)
1037                    throws PortalException {
1038    
1039                    // Entry
1040    
1041                    int oldStatus = entry.getStatus();
1042    
1043                    if (oldStatus == WorkflowConstants.STATUS_PENDING) {
1044                            entry.setStatus(WorkflowConstants.STATUS_DRAFT);
1045    
1046                            blogsEntryPersistence.update(entry);
1047                    }
1048    
1049                    entry = updateStatus(
1050                            userId, entry.getEntryId(), WorkflowConstants.STATUS_IN_TRASH,
1051                            new ServiceContext());
1052    
1053                    // Social
1054    
1055                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1056    
1057                    extraDataJSONObject.put("title", entry.getTitle());
1058    
1059                    socialActivityLocalService.addActivity(
1060                            userId, entry.getGroupId(), BlogsEntry.class.getName(),
1061                            entry.getEntryId(), SocialActivityConstants.TYPE_MOVE_TO_TRASH,
1062                            extraDataJSONObject.toString(), 0);
1063    
1064                    // Workflow
1065    
1066                    if (oldStatus == WorkflowConstants.STATUS_PENDING) {
1067                            workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
1068                                    entry.getCompanyId(), entry.getGroupId(),
1069                                    BlogsEntry.class.getName(), entry.getEntryId());
1070                    }
1071    
1072                    return entry;
1073            }
1074    
1075            /**
1076             * Moves the blogs entry with the ID to the recycle bin.
1077             *
1078             * @param  userId the primary key of the user moving the blogs entry
1079             * @param  entryId the primary key of the blogs entry to be moved
1080             * @return the moved blogs entry
1081             * @throws PortalException if a user or blogs entry with the primary key
1082             *         could not be found or if the blogs entry owner's social activity
1083             *         counter could not be updated
1084             */
1085            @Override
1086            public BlogsEntry moveEntryToTrash(long userId, long entryId)
1087                    throws PortalException {
1088    
1089                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
1090    
1091                    return blogsEntryLocalService.moveEntryToTrash(userId, entry);
1092            }
1093    
1094            /**
1095             * Restores the blogs entry with the ID from the recycle bin. Social
1096             * activity counters for this entry get activated.
1097             *
1098             * @param  userId the primary key of the user restoring the blogs entry
1099             * @param  entryId the primary key of the blogs entry to be restored
1100             * @return the restored blogs entry from the recycle bin
1101             * @throws PortalException if a user or blogs entry with the primary key
1102             *         could not be found or if the blogs entry owner's social activity
1103             *         counter could not be updated
1104             */
1105            @Indexable(type = IndexableType.REINDEX)
1106            @Override
1107            public BlogsEntry restoreEntryFromTrash(long userId, long entryId)
1108                    throws PortalException {
1109    
1110                    // Entry
1111    
1112                    TrashEntry trashEntry = trashEntryLocalService.getEntry(
1113                            BlogsEntry.class.getName(), entryId);
1114    
1115                    BlogsEntry entry = updateStatus(
1116                            userId, entryId, trashEntry.getStatus(), new ServiceContext());
1117    
1118                    // Social
1119    
1120                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1121    
1122                    extraDataJSONObject.put("title", entry.getTitle());
1123    
1124                    socialActivityLocalService.addActivity(
1125                            userId, trashEntry.getGroupId(), BlogsEntry.class.getName(),
1126                            entryId, SocialActivityConstants.TYPE_RESTORE_FROM_TRASH,
1127                            extraDataJSONObject.toString(), 0);
1128    
1129                    return entry;
1130            }
1131    
1132            @Override
1133            public void subscribe(long userId, long groupId) throws PortalException {
1134                    subscriptionLocalService.addSubscription(
1135                            userId, groupId, BlogsEntry.class.getName(), groupId);
1136            }
1137    
1138            @Override
1139            public void unsubscribe(long userId, long groupId) throws PortalException {
1140                    subscriptionLocalService.deleteSubscription(
1141                            userId, BlogsEntry.class.getName(), groupId);
1142            }
1143    
1144            @Override
1145            public void updateAsset(
1146                            long userId, BlogsEntry entry, long[] assetCategoryIds,
1147                            String[] assetTagNames, long[] assetLinkEntryIds)
1148                    throws PortalException {
1149    
1150                    boolean visible = false;
1151    
1152                    if (entry.isApproved()) {
1153                            visible = true;
1154                    }
1155    
1156                    String summary = HtmlUtil.extractText(
1157                            StringUtil.shorten(entry.getContent(), 500));
1158    
1159                    AssetEntry assetEntry = assetEntryLocalService.updateEntry(
1160                            userId, entry.getGroupId(), entry.getCreateDate(),
1161                            entry.getModifiedDate(), BlogsEntry.class.getName(),
1162                            entry.getEntryId(), entry.getUuid(), 0, assetCategoryIds,
1163                            assetTagNames, visible, null, null, null, ContentTypes.TEXT_HTML,
1164                            entry.getTitle(), entry.getDescription(), summary, null, null, 0, 0,
1165                            null);
1166    
1167                    assetLinkLocalService.updateLinks(
1168                            userId, assetEntry.getEntryId(), assetLinkEntryIds,
1169                            AssetLinkConstants.TYPE_RELATED);
1170            }
1171    
1172            @Override
1173            public BlogsEntry updateEntry(
1174                            long userId, long entryId, String title, String content,
1175                            ServiceContext serviceContext)
1176                    throws PortalException {
1177    
1178                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
1179    
1180                    return updateEntry(
1181                            userId, entryId, title, entry.getSubtitle(), entry.getDescription(),
1182                            content, entry.getDisplayDate(), entry.getAllowPingbacks(),
1183                            entry.getAllowTrackbacks(), StringUtil.split(entry.getTrackbacks()),
1184                            StringPool.BLANK, null, null, serviceContext);
1185            }
1186    
1187            /**
1188             * @deprecated As of 7.0.0, replaced by {@link #updateEntry(long, long,
1189             *             String, String, String, String, int, int, int, int, int,
1190             *             boolean, boolean, String[], String, ImageSelector,
1191             *             ImageSelector, ServiceContext)}
1192             */
1193            @Deprecated
1194            @Override
1195            public BlogsEntry updateEntry(
1196                            long userId, long entryId, String title, String description,
1197                            String content, int displayDateMonth, int displayDateDay,
1198                            int displayDateYear, int displayDateHour, int displayDateMinute,
1199                            boolean allowPingbacks, boolean allowTrackbacks,
1200                            String[] trackbacks, boolean smallImage, String smallImageURL,
1201                            String smallImageFileName, InputStream smallImageInputStream,
1202                            ServiceContext serviceContext)
1203                    throws PortalException {
1204    
1205                    ImageSelector coverImageImageSelector = null;
1206                    ImageSelector smallImageImageSelector = null;
1207    
1208                    if (smallImage) {
1209                            if (Validator.isNotNull(smallImageFileName) &&
1210                                    (smallImageInputStream != null)) {
1211    
1212                                    FileEntry tempFileEntry = TempFileEntryUtil.addTempFileEntry(
1213                                            serviceContext.getScopeGroupId(), userId,
1214                                            BlogsEntry.class.getName(), smallImageFileName,
1215                                            smallImageInputStream,
1216                                            MimeTypesUtil.getContentType(smallImageFileName));
1217    
1218                                    smallImageImageSelector = new ImageSelector(
1219                                            tempFileEntry.getFileEntryId(), smallImageURL, null);
1220                            }
1221                    }
1222                    else {
1223                            smallImageImageSelector = new ImageSelector(0);
1224                    }
1225    
1226                    return updateEntry(
1227                            userId, entryId, title, StringPool.BLANK, description, content,
1228                            displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
1229                            displayDateMinute, allowPingbacks, allowTrackbacks, trackbacks,
1230                            StringPool.BLANK, coverImageImageSelector, smallImageImageSelector,
1231                            serviceContext);
1232            }
1233    
1234            @Indexable(type = IndexableType.REINDEX)
1235            @Override
1236            public BlogsEntry updateEntry(
1237                            long userId, long entryId, String title, String subtitle,
1238                            String description, String content, Date displayDate,
1239                            boolean allowPingbacks, boolean allowTrackbacks,
1240                            String[] trackbacks, String coverImageCaption,
1241                            ImageSelector coverImageImageSelector,
1242                            ImageSelector smallImageImageSelector,
1243                            ServiceContext serviceContext)
1244                    throws PortalException {
1245    
1246                    // Entry
1247    
1248                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
1249    
1250                    validate(title, content);
1251    
1252                    String oldUrlTitle = entry.getUrlTitle();
1253    
1254                    entry.setTitle(title);
1255                    entry.setSubtitle(subtitle);
1256                    entry.setUrlTitle(
1257                            getUniqueUrlTitle(entryId, title, oldUrlTitle, serviceContext));
1258                    entry.setDescription(description);
1259                    entry.setContent(content);
1260                    entry.setDisplayDate(displayDate);
1261                    entry.setAllowPingbacks(allowPingbacks);
1262                    entry.setAllowTrackbacks(allowTrackbacks);
1263    
1264                    if (entry.isPending() || entry.isDraft()) {
1265                    }
1266                    else {
1267                            entry.setStatus(WorkflowConstants.STATUS_DRAFT);
1268                    }
1269    
1270                    entry.setExpandoBridgeAttributes(serviceContext);
1271    
1272                    blogsEntryPersistence.update(entry);
1273    
1274                    // Resources
1275    
1276                    if ((serviceContext.getGroupPermissions() != null) ||
1277                            (serviceContext.getGuestPermissions() != null)) {
1278    
1279                            updateEntryResources(
1280                                    entry, serviceContext.getGroupPermissions(),
1281                                    serviceContext.getGuestPermissions());
1282                    }
1283    
1284                    // Asset
1285    
1286                    updateAsset(
1287                            userId, entry, serviceContext.getAssetCategoryIds(),
1288                            serviceContext.getAssetTagNames(),
1289                            serviceContext.getAssetLinkEntryIds());
1290    
1291                    // Images
1292    
1293                    long coverImageFileEntryId = entry.getCoverImageFileEntryId();
1294                    String coverImageURL = entry.getCoverImageURL();
1295    
1296                    long deletePreviousCoverImageFileEntryId = 0;
1297    
1298                    if (coverImageImageSelector != null) {
1299                            coverImageFileEntryId = coverImageImageSelector.getImageId();
1300                            coverImageURL = coverImageImageSelector.getImageURL();
1301    
1302                            if (coverImageImageSelector.getImageId() == 0) {
1303                                    if (entry.getCoverImageFileEntryId() != 0) {
1304                                            deletePreviousCoverImageFileEntryId =
1305                                                    entry.getCoverImageFileEntryId();
1306                                    }
1307                            }
1308                            else if (coverImageImageSelector.getImageId() !=
1309                                                    entry.getCoverImageFileEntryId()) {
1310    
1311                                    if (entry.getCoverImageFileEntryId() != 0) {
1312                                            deletePreviousCoverImageFileEntryId =
1313                                                    entry.getCoverImageFileEntryId();
1314                                    }
1315    
1316                                    if (coverImageImageSelector.getImageId() != 0) {
1317                                            coverImageFileEntryId = addCoverImage(
1318                                                    userId, entry.getGroupId(), entryId,
1319                                                    coverImageImageSelector);
1320                                    }
1321                            }
1322                    }
1323    
1324                    boolean smallImage = entry.isSmallImage();
1325                    long smallImageFileEntryId = entry.getSmallImageFileEntryId();
1326                    String smallImageURL = entry.getSmallImageURL();
1327    
1328                    FileEntry tempSmallImageFileEntry = null;
1329    
1330                    long deletePreviousSmallImageFileEntryId = 0;
1331    
1332                    if (smallImageImageSelector != null) {
1333                            smallImage = !smallImageImageSelector.isRemoveSmallImage();
1334                            smallImageFileEntryId = smallImageImageSelector.getImageId();
1335                            smallImageURL = smallImageImageSelector.getImageURL();
1336    
1337                            if (smallImageImageSelector.getImageId() == 0) {
1338                                    if (entry.getSmallImageFileEntryId() != 0) {
1339                                            deletePreviousSmallImageFileEntryId =
1340                                                    entry.getSmallImageFileEntryId();
1341                                    }
1342                            }
1343                            else if (smallImageImageSelector.getImageId() !=
1344                                                    entry.getSmallImageFileEntryId()) {
1345    
1346                                    if (entry.getSmallImageFileEntryId() != 0) {
1347                                            deletePreviousSmallImageFileEntryId =
1348                                                    entry.getSmallImageFileEntryId();
1349                                    }
1350    
1351                                    tempSmallImageFileEntry =
1352                                            PortletFileRepositoryUtil.getPortletFileEntry(
1353                                                    smallImageImageSelector.getImageId());
1354    
1355                                    smallImageFileEntryId = addSmallImageFileEntry(
1356                                            userId, entry.getGroupId(), entry.getEntryId(),
1357                                            tempSmallImageFileEntry.getMimeType(),
1358                                            tempSmallImageFileEntry.getTitle(),
1359                                            tempSmallImageFileEntry.getContentStream());
1360                            }
1361                    }
1362    
1363                    validate(smallImageFileEntryId);
1364    
1365                    entry.setCoverImageCaption(coverImageCaption);
1366                    entry.setCoverImageFileEntryId(coverImageFileEntryId);
1367                    entry.setCoverImageURL(coverImageURL);
1368                    entry.setSmallImage(smallImage);
1369                    entry.setSmallImageFileEntryId(smallImageFileEntryId);
1370                    entry.setSmallImageURL(smallImageURL);
1371    
1372                    blogsEntryPersistence.update(entry);
1373    
1374                    // Workflow
1375    
1376                    boolean pingOldTrackbacks = false;
1377    
1378                    if (!oldUrlTitle.equals(entry.getUrlTitle())) {
1379                            pingOldTrackbacks = true;
1380                    }
1381    
1382                    serviceContext.setAttribute(
1383                            "pingOldTrackbacks", String.valueOf(pingOldTrackbacks));
1384    
1385                    if (ArrayUtil.isNotEmpty(trackbacks)) {
1386                            serviceContext.setAttribute("trackbacks", trackbacks);
1387                    }
1388                    else {
1389                            serviceContext.setAttribute("trackbacks", null);
1390                    }
1391    
1392                    entry = startWorkflowInstance(userId, entry, serviceContext);
1393    
1394                    if (deletePreviousCoverImageFileEntryId != 0) {
1395                            PortletFileRepositoryUtil.deletePortletFileEntry(
1396                                    deletePreviousCoverImageFileEntryId);
1397                    }
1398    
1399                    if (deletePreviousSmallImageFileEntryId != 0) {
1400                            PortletFileRepositoryUtil.deletePortletFileEntry(
1401                                    deletePreviousSmallImageFileEntryId);
1402                    }
1403    
1404                    if ((coverImageImageSelector != null) &&
1405                            (coverImageImageSelector.getImageId() != 0) &&
1406                            (coverImageImageSelector.getImageId() !=
1407                                    entry.getCoverImageFileEntryId())) {
1408    
1409                            PortletFileRepositoryUtil.deletePortletFileEntry(
1410                                    coverImageImageSelector.getImageId());
1411                    }
1412    
1413                    if (tempSmallImageFileEntry != null) {
1414                            PortletFileRepositoryUtil.deletePortletFileEntry(
1415                                    tempSmallImageFileEntry.getFileEntryId());
1416                    }
1417    
1418                    return entry;
1419            }
1420    
1421            @Override
1422            public BlogsEntry updateEntry(
1423                            long userId, long entryId, String title, String subtitle,
1424                            String description, String content, int displayDateMonth,
1425                            int displayDateDay, int displayDateYear, int displayDateHour,
1426                            int displayDateMinute, boolean allowPingbacks,
1427                            boolean allowTrackbacks, String[] trackbacks,
1428                            String coverImageCaption, ImageSelector coverImageImageSelector,
1429                            ImageSelector smallImageImageSelector,
1430                            ServiceContext serviceContext)
1431                    throws PortalException {
1432    
1433                    User user = userPersistence.findByPrimaryKey(userId);
1434    
1435                    Date displayDate = PortalUtil.getDate(
1436                            displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
1437                            displayDateMinute, user.getTimeZone(),
1438                            EntryDisplayDateException.class);
1439    
1440                    return updateEntry(
1441                            userId, entryId, title, subtitle, description, content, displayDate,
1442                            allowPingbacks, allowTrackbacks, trackbacks, coverImageCaption,
1443                            coverImageImageSelector, smallImageImageSelector, serviceContext);
1444            }
1445    
1446            @Override
1447            public void updateEntryResources(
1448                            BlogsEntry entry, String[] groupPermissions,
1449                            String[] guestPermissions)
1450                    throws PortalException {
1451    
1452                    resourceLocalService.updateResources(
1453                            entry.getCompanyId(), entry.getGroupId(),
1454                            BlogsEntry.class.getName(), entry.getEntryId(), groupPermissions,
1455                            guestPermissions);
1456            }
1457    
1458            /**
1459             * @deprecated As of 7.0.0, replaced by {@link #updateStatus(long, long,
1460             *             int, ServiceContext, Map)}
1461             */
1462            @Deprecated
1463            @Override
1464            public BlogsEntry updateStatus(
1465                            long userId, long entryId, int status,
1466                            ServiceContext serviceContext)
1467                    throws PortalException {
1468    
1469                    return updateStatus(
1470                            userId, entryId, status, serviceContext,
1471                            new HashMap<String, Serializable>());
1472            }
1473    
1474            @Indexable(type = IndexableType.REINDEX)
1475            @Override
1476            public BlogsEntry updateStatus(
1477                            long userId, long entryId, int status,
1478                            ServiceContext serviceContext,
1479                            Map<String, Serializable> workflowContext)
1480                    throws PortalException {
1481    
1482                    // Entry
1483    
1484                    User user = userPersistence.findByPrimaryKey(userId);
1485                    Date now = new Date();
1486    
1487                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
1488    
1489                    int oldStatus = entry.getStatus();
1490    
1491                    if ((status == WorkflowConstants.STATUS_APPROVED) &&
1492                            now.before(entry.getDisplayDate())) {
1493    
1494                            status = WorkflowConstants.STATUS_SCHEDULED;
1495                    }
1496    
1497                    entry.setStatus(status);
1498                    entry.setStatusByUserId(user.getUserId());
1499                    entry.setStatusByUserName(user.getFullName());
1500                    entry.setStatusDate(serviceContext.getModifiedDate(now));
1501    
1502                    blogsEntryPersistence.update(entry);
1503    
1504                    // Statistics
1505    
1506                    blogsStatsUserLocalService.updateStatsUser(
1507                            entry.getGroupId(), entry.getUserId(), entry.getDisplayDate());
1508    
1509                    AssetEntry assetEntry = assetEntryLocalService.fetchEntry(
1510                            BlogsEntry.class.getName(), entryId);
1511    
1512                    if ((assetEntry == null) || (assetEntry.getPublishDate() == null)) {
1513                            serviceContext.setCommand(Constants.ADD);
1514                    }
1515    
1516                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1517    
1518                    extraDataJSONObject.put("title", entry.getTitle());
1519    
1520                    if (status == WorkflowConstants.STATUS_APPROVED) {
1521    
1522                            // Asset
1523    
1524                            assetEntryLocalService.updateEntry(
1525                                    BlogsEntry.class.getName(), entryId, entry.getDisplayDate(),
1526                                    true);
1527    
1528                            // Social
1529    
1530                            if ((oldStatus != WorkflowConstants.STATUS_IN_TRASH) &&
1531                                    (oldStatus != WorkflowConstants.STATUS_SCHEDULED)) {
1532    
1533                                    if (serviceContext.isCommandUpdate()) {
1534                                            socialActivityLocalService.addActivity(
1535                                                    user.getUserId(), entry.getGroupId(),
1536                                                    BlogsEntry.class.getName(), entryId,
1537                                                    BlogsActivityKeys.UPDATE_ENTRY,
1538                                                    extraDataJSONObject.toString(), 0);
1539                                    }
1540                                    else {
1541                                            socialActivityLocalService.addUniqueActivity(
1542                                                    user.getUserId(), entry.getGroupId(),
1543                                                    BlogsEntry.class.getName(), entryId,
1544                                                    BlogsActivityKeys.ADD_ENTRY,
1545                                                    extraDataJSONObject.toString(), 0);
1546                                    }
1547                            }
1548    
1549                            // Trash
1550    
1551                            if (oldStatus == WorkflowConstants.STATUS_IN_TRASH) {
1552                                    trashEntryLocalService.deleteEntry(
1553                                            BlogsEntry.class.getName(), entryId);
1554                            }
1555    
1556                            if (oldStatus != WorkflowConstants.STATUS_IN_TRASH) {
1557    
1558                                    // Subscriptions
1559    
1560                                    notifySubscribers(
1561                                            userId, entry, serviceContext, workflowContext);
1562    
1563                                    // Ping
1564    
1565                                    String[] trackbacks = (String[])serviceContext.getAttribute(
1566                                            "trackbacks");
1567                                    Boolean pingOldTrackbacks = ParamUtil.getBoolean(
1568                                            serviceContext, "pingOldTrackbacks");
1569    
1570                                    pingGoogle(entry, serviceContext);
1571                                    pingPingback(entry, serviceContext);
1572                                    pingTrackbacks(
1573                                            entry, trackbacks, pingOldTrackbacks, serviceContext);
1574                            }
1575                    }
1576                    else {
1577    
1578                            // Asset
1579    
1580                            assetEntryLocalService.updateVisible(
1581                                    BlogsEntry.class.getName(), entryId, false);
1582    
1583                            // Social
1584    
1585                            if ((status == WorkflowConstants.STATUS_SCHEDULED) &&
1586                                    (oldStatus != WorkflowConstants.STATUS_IN_TRASH)) {
1587    
1588                                    if (serviceContext.isCommandUpdate()) {
1589                                            socialActivityLocalService.addActivity(
1590                                                    user.getUserId(), entry.getGroupId(),
1591                                                    BlogsEntry.class.getName(), entryId,
1592                                                    BlogsActivityKeys.UPDATE_ENTRY,
1593                                                    extraDataJSONObject.toString(), 0);
1594                                    }
1595                                    else {
1596                                            socialActivityLocalService.addUniqueActivity(
1597                                                    user.getUserId(), entry.getGroupId(),
1598                                                    BlogsEntry.class.getName(), entryId,
1599                                                    BlogsActivityKeys.ADD_ENTRY,
1600                                                    extraDataJSONObject.toString(), 0);
1601                                    }
1602                            }
1603    
1604                            // Trash
1605    
1606                            if (status == WorkflowConstants.STATUS_IN_TRASH) {
1607                                    trashEntryLocalService.addTrashEntry(
1608                                            userId, entry.getGroupId(), BlogsEntry.class.getName(),
1609                                            entry.getEntryId(), entry.getUuid(), null, oldStatus, null,
1610                                            null);
1611                            }
1612                            else if (oldStatus == WorkflowConstants.STATUS_IN_TRASH) {
1613                                    trashEntryLocalService.deleteEntry(
1614                                            BlogsEntry.class.getName(), entryId);
1615                            }
1616                    }
1617    
1618                    return entry;
1619            }
1620    
1621            protected long addCoverImage(
1622                            long userId, long groupId, long entryId,
1623                            ImageSelector coverImageImageSelector)
1624                    throws PortalException {
1625    
1626                    long coverImageId = 0;
1627    
1628                    byte[] bytes = null;
1629    
1630                    try {
1631                            bytes = coverImageImageSelector.getCroppedImageBytes();
1632                    }
1633                    catch (IOException ioe) {
1634                            if (_log.isDebugEnabled()) {
1635                                    _log.debug(
1636                                            "Unable to get cropped image from image selector image " +
1637                                                    coverImageImageSelector.getImageId());
1638                            }
1639                    }
1640    
1641                    if (bytes == null) {
1642                            return 0;
1643                    }
1644    
1645                    File file = null;
1646    
1647                    try {
1648                            file = FileUtil.createTempFile(bytes);
1649    
1650                            String title = coverImageImageSelector.getTitle();
1651                            String mimeType = coverImageImageSelector.getMimeType();
1652    
1653                            if (Validator.isNull(title)) {
1654                                    title =
1655                                            StringUtil.randomString() + "_tempCroppedImage_" + entryId;
1656                            }
1657    
1658                            ServiceContext serviceContext = new ServiceContext();
1659    
1660                            serviceContext.setAddGroupPermissions(true);
1661                            serviceContext.setAddGuestPermissions(true);
1662    
1663                            Folder folder = addAttachmentsFolder(userId, groupId);
1664    
1665                            FileEntry fileEntry = PortletFileRepositoryUtil.addPortletFileEntry(
1666                                    groupId, userId, BlogsEntry.class.getName(), entryId,
1667                                    PortletKeys.BLOGS, folder.getFolderId(), file, title, mimeType,
1668                                    false);
1669    
1670                            coverImageId = fileEntry.getFileEntryId();
1671                    }
1672                    catch (IOException ioe) {
1673                            if (_log.isDebugEnabled()) {
1674                                    _log.debug(
1675                                            "Unable to get cropped image from image selector image " +
1676                                                    coverImageImageSelector.getImageId());
1677                            }
1678                    }
1679                    finally {
1680                            FileUtil.delete(file);
1681                    }
1682    
1683                    return coverImageId;
1684            }
1685    
1686            protected void addDiscussion(BlogsEntry entry, long userId, long groupId)
1687                    throws PortalException {
1688    
1689                    if (PropsValues.BLOGS_ENTRY_COMMENTS_ENABLED) {
1690                            commentManager.addDiscussion(
1691                                    userId, groupId, BlogsEntry.class.getName(), entry.getEntryId(),
1692                                    entry.getUserName());
1693                    }
1694            }
1695    
1696            protected long addSmallImageFileEntry(
1697                            long userId, long groupId, long entryId, String mimeType,
1698                            String title, InputStream is)
1699                    throws PortalException {
1700    
1701                    ServiceContext serviceContext = new ServiceContext();
1702    
1703                    serviceContext.setAddGroupPermissions(true);
1704                    serviceContext.setAddGuestPermissions(true);
1705    
1706                    Folder folder = addAttachmentsFolder(userId, groupId);
1707    
1708                    FileEntry fileEntry = PortletFileRepositoryUtil.addPortletFileEntry(
1709                            groupId, userId, BlogsEntry.class.getName(), entryId,
1710                            PortletKeys.BLOGS, folder.getFolderId(), is, title, mimeType,
1711                            false);
1712    
1713                    return fileEntry.getFileEntryId();
1714            }
1715    
1716            protected void deleteDiscussion(BlogsEntry entry) throws PortalException {
1717                    commentManager.deleteDiscussion(
1718                            BlogsEntry.class.getName(), entry.getEntryId());
1719            }
1720    
1721            protected String getEntryURL(
1722                            BlogsEntry entry, ServiceContext serviceContext)
1723                    throws PortalException {
1724    
1725                    String entryURL = GetterUtil.getString(
1726                            serviceContext.getAttribute("entryURL"));
1727    
1728                    if (Validator.isNotNull(entryURL)) {
1729                            return entryURL;
1730                    }
1731    
1732                    HttpServletRequest request = serviceContext.getRequest();
1733    
1734                    if (request == null) {
1735                            return StringPool.BLANK;
1736                    }
1737    
1738                    String layoutURL = LayoutURLUtil.getLayoutURL(
1739                            entry.getGroupId(), PortletKeys.BLOGS, serviceContext);
1740    
1741                    if (Validator.isNotNull(layoutURL)) {
1742                            return layoutURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs" +
1743                                    StringPool.SLASH + entry.getEntryId();
1744                    }
1745    
1746                    long controlPanelPlid = PortalUtil.getControlPanelPlid(
1747                            serviceContext.getCompanyId());
1748    
1749                    PortletURL portletURL = PortletURLFactoryUtil.create(
1750                            request, PortletKeys.BLOGS_ADMIN, controlPanelPlid,
1751                            PortletRequest.RENDER_PHASE);
1752    
1753                    portletURL.setParameter("struts_action", "/blogs_admin/view_entry");
1754                    portletURL.setParameter("entryId", String.valueOf(entry.getEntryId()));
1755    
1756                    return portletURL.toString();
1757            }
1758    
1759            protected String getUniqueUrlTitle(
1760                    long entryId, long groupId, String title) {
1761    
1762                    String urlTitle = BlogsUtil.getUrlTitle(entryId, title);
1763    
1764                    for (int i = 1;; i++) {
1765                            BlogsEntry entry = blogsEntryPersistence.fetchByG_UT(
1766                                    groupId, urlTitle);
1767    
1768                            if ((entry == null) || (entryId == entry.getEntryId())) {
1769                                    break;
1770                            }
1771                            else {
1772                                    String suffix = StringPool.DASH + i;
1773    
1774                                    String prefix = urlTitle;
1775    
1776                                    if (urlTitle.length() > suffix.length()) {
1777                                            prefix = urlTitle.substring(
1778                                                    0, urlTitle.length() - suffix.length());
1779                                    }
1780    
1781                                    urlTitle = prefix + suffix;
1782                            }
1783                    }
1784    
1785                    return urlTitle;
1786            }
1787    
1788            protected String getUniqueUrlTitle(
1789                    long entryId, String title, String oldUrlTitle,
1790                    ServiceContext serviceContext) {
1791    
1792                    String serviceContextUrlTitle = ParamUtil.getString(
1793                            serviceContext, "urlTitle");
1794    
1795                    String urlTitle = null;
1796    
1797                    if (Validator.isNotNull(serviceContextUrlTitle)) {
1798                            urlTitle = BlogsUtil.getUrlTitle(entryId, serviceContextUrlTitle);
1799                    }
1800                    else if (Validator.isNotNull(oldUrlTitle)) {
1801                            return oldUrlTitle;
1802                    }
1803                    else {
1804                            urlTitle = getUniqueUrlTitle(
1805                                    entryId, serviceContext.getScopeGroupId(), title);
1806                    }
1807    
1808                    BlogsEntry urlTitleEntry = blogsEntryPersistence.fetchByG_UT(
1809                            serviceContext.getScopeGroupId(), urlTitle);
1810    
1811                    if ((urlTitleEntry != null) &&
1812                            (urlTitleEntry.getEntryId() != entryId)) {
1813    
1814                            urlTitle = getUniqueUrlTitle(
1815                                    entryId, serviceContext.getScopeGroupId(), urlTitle);
1816                    }
1817    
1818                    return urlTitle;
1819            }
1820    
1821            protected void notifySubscribers(
1822                            long userId, BlogsEntry entry, ServiceContext serviceContext,
1823                            Map<String, Serializable> workflowContext)
1824                    throws PortalException {
1825    
1826                    String entryURL = (String)workflowContext.get(
1827                            WorkflowConstants.CONTEXT_URL);
1828    
1829                    if (!entry.isApproved() || Validator.isNull(entryURL)) {
1830                            return;
1831                    }
1832    
1833                    BlogsGroupServiceSettings blogsGroupServiceSettings =
1834                            BlogsGroupServiceSettings.getInstance(entry.getGroupId());
1835    
1836                    boolean sendEmailEntryUpdated = GetterUtil.getBoolean(
1837                            serviceContext.getAttribute("sendEmailEntryUpdated"));
1838    
1839                    if (serviceContext.isCommandAdd() &&
1840                            blogsGroupServiceSettings.isEmailEntryAddedEnabled()) {
1841                    }
1842                    else if (sendEmailEntryUpdated && serviceContext.isCommandUpdate() &&
1843                                     blogsGroupServiceSettings.isEmailEntryUpdatedEnabled()) {
1844                    }
1845                    else {
1846                            return;
1847                    }
1848    
1849                    Group group = groupPersistence.findByPrimaryKey(entry.getGroupId());
1850    
1851                    String entryTitle = entry.getTitle();
1852    
1853                    String fromName = blogsGroupServiceSettings.getEmailFromName();
1854                    String fromAddress = blogsGroupServiceSettings.getEmailFromAddress();
1855    
1856                    LocalizedValuesMap subjectLocalizedValuesMap = null;
1857                    LocalizedValuesMap bodyLocalizedValuesMap = null;
1858    
1859                    if (serviceContext.isCommandUpdate()) {
1860                            subjectLocalizedValuesMap =
1861                                    blogsGroupServiceSettings.getEmailEntryUpdatedSubject();
1862                            bodyLocalizedValuesMap =
1863                                    blogsGroupServiceSettings.getEmailEntryUpdatedBody();
1864                    }
1865                    else {
1866                            subjectLocalizedValuesMap =
1867                                    blogsGroupServiceSettings.getEmailEntryAddedSubject();
1868                            bodyLocalizedValuesMap =
1869                                    blogsGroupServiceSettings.getEmailEntryAddedBody();
1870                    }
1871    
1872                    SubscriptionSender subscriptionSender =
1873                            new GroupSubscriptionCheckSubscriptionSender(
1874                                    BlogsPermission.RESOURCE_NAME);
1875    
1876                    subscriptionSender.setClassPK(entry.getEntryId());
1877                    subscriptionSender.setClassName(entry.getModelClassName());
1878                    subscriptionSender.setCompanyId(entry.getCompanyId());
1879                    subscriptionSender.setContextAttribute(
1880                            "[$BLOGS_ENTRY_CONTENT$]",
1881                            StringUtil.shorten(HtmlUtil.stripHtml(entry.getContent()), 500),
1882                            false);
1883                    subscriptionSender.setContextAttributes(
1884                            "[$BLOGS_ENTRY_CREATE_DATE$]",
1885                            Time.getSimpleDate(entry.getCreateDate(), "yyyy/MM/dd"),
1886                            "[$BLOGS_ENTRY_DESCRIPTION$]", entry.getDescription(),
1887                            "[$BLOGS_ENTRY_SITE_NAME$]",
1888                                    group.getDescriptiveName(serviceContext.getLocale()),
1889                            "[$BLOGS_ENTRY_STATUS_BY_USER_NAME$]", entry.getStatusByUserName(),
1890                            "[$BLOGS_ENTRY_TITLE$]", entryTitle,
1891                            "[$BLOGS_ENTRY_UPDATE_COMMENT$]",
1892                            HtmlUtil.replaceNewLine(
1893                                    GetterUtil.getString(
1894                                            serviceContext.getAttribute("emailEntryUpdatedComment"))),
1895                            "[$BLOGS_ENTRY_URL$]", entryURL,
1896                            "[$BLOGS_ENTRY_USER_PORTRAIT_URL$]",
1897                            workflowContext.get(WorkflowConstants.CONTEXT_USER_PORTRAIT_URL),
1898                            "[$BLOGS_ENTRY_USER_URL$]",
1899                            workflowContext.get(WorkflowConstants.CONTEXT_USER_URL));
1900                    subscriptionSender.setContextCreatorUserPrefix("BLOGS_ENTRY");
1901                    subscriptionSender.setCreatorUserId(entry.getUserId());
1902                    subscriptionSender.setCurrentUserId(userId);
1903                    subscriptionSender.setEntryTitle(entryTitle);
1904                    subscriptionSender.setEntryURL(entryURL);
1905                    subscriptionSender.setFrom(fromAddress, fromName);
1906                    subscriptionSender.setHtmlFormat(true);
1907    
1908                    if (bodyLocalizedValuesMap != null) {
1909                            subscriptionSender.setLocalizedBodyMap(
1910                                    LocalizationUtil.getMap(bodyLocalizedValuesMap));
1911                    }
1912    
1913                    if (subjectLocalizedValuesMap != null) {
1914                            subscriptionSender.setLocalizedSubjectMap(
1915                                    LocalizationUtil.getMap(subjectLocalizedValuesMap));
1916                    }
1917    
1918                    subscriptionSender.setMailId("blogs_entry", entry.getEntryId());
1919    
1920                    int notificationType =
1921                            UserNotificationDefinition.NOTIFICATION_TYPE_ADD_ENTRY;
1922    
1923                    if (serviceContext.isCommandUpdate()) {
1924                            notificationType =
1925                                    UserNotificationDefinition.NOTIFICATION_TYPE_UPDATE_ENTRY;
1926                    }
1927    
1928                    subscriptionSender.setNotificationType(notificationType);
1929    
1930                    subscriptionSender.setPortletId(PortletKeys.BLOGS);
1931                    subscriptionSender.setReplyToAddress(fromAddress);
1932                    subscriptionSender.setScopeGroupId(entry.getGroupId());
1933                    subscriptionSender.setServiceContext(serviceContext);
1934    
1935                    subscriptionSender.addPersistedSubscribers(
1936                            BlogsEntry.class.getName(), entry.getGroupId());
1937    
1938                    subscriptionSender.addPersistedSubscribers(
1939                            BlogsEntry.class.getName(), entry.getEntryId());
1940    
1941                    subscriptionSender.flushNotificationsAsync();
1942            }
1943    
1944            protected void pingGoogle(BlogsEntry entry, ServiceContext serviceContext)
1945                    throws PortalException {
1946    
1947                    if (!PropsValues.BLOGS_PING_GOOGLE_ENABLED || !entry.isApproved()) {
1948                            return;
1949                    }
1950    
1951                    String layoutFullURL = PortalUtil.getLayoutFullURL(
1952                            serviceContext.getScopeGroupId(), PortletKeys.BLOGS);
1953    
1954                    if (Validator.isNull(layoutFullURL)) {
1955                            return;
1956                    }
1957    
1958                    if (layoutFullURL.contains("://localhost")) {
1959                            if (_log.isDebugEnabled()) {
1960                                    _log.debug(
1961                                            "Not pinging Google because of localhost URL " +
1962                                                    layoutFullURL);
1963                            }
1964    
1965                            return;
1966                    }
1967    
1968                    Group group = groupPersistence.findByPrimaryKey(entry.getGroupId());
1969    
1970                    StringBundler sb = new StringBundler(6);
1971    
1972                    String name = group.getDescriptiveName();
1973                    String url = layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs";
1974                    String changesURL =
1975                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/rss";
1976    
1977                    sb.append("http://blogsearch.google.com/ping?name=");
1978                    sb.append(HttpUtil.encodeURL(name));
1979                    sb.append("&url=");
1980                    sb.append(HttpUtil.encodeURL(url));
1981                    sb.append("&changesURL=");
1982                    sb.append(HttpUtil.encodeURL(changesURL));
1983    
1984                    String location = sb.toString();
1985    
1986                    if (_log.isInfoEnabled()) {
1987                            _log.info("Pinging Google at " + location);
1988                    }
1989    
1990                    try {
1991                            String response = HttpUtil.URLtoString(sb.toString());
1992    
1993                            if (_log.isInfoEnabled()) {
1994                                    _log.info("Google ping response: " + response);
1995                            }
1996                    }
1997                    catch (IOException ioe) {
1998                            _log.error("Unable to ping Google at " + location, ioe);
1999                    }
2000            }
2001    
2002            protected void pingPingback(BlogsEntry entry, ServiceContext serviceContext)
2003                    throws PortalException {
2004    
2005                    if (!PropsValues.BLOGS_PINGBACK_ENABLED ||
2006                            !entry.isAllowPingbacks() || !entry.isApproved()) {
2007    
2008                            return;
2009                    }
2010    
2011                    HttpServletRequest request = serviceContext.getRequest();
2012    
2013                    if (request == null) {
2014                            return;
2015                    }
2016    
2017                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
2018                            WebKeys.THEME_DISPLAY);
2019    
2020                    String layoutFullURL = PortalUtil.getLayoutFullURL(themeDisplay);
2021    
2022                    if (Validator.isNull(layoutFullURL)) {
2023                            return;
2024                    }
2025    
2026                    String sourceUri =
2027                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/" +
2028                                    entry.getUrlTitle();
2029    
2030                    Source source = new Source(entry.getContent());
2031    
2032                    List<StartTag> tags = source.getAllStartTags("a");
2033    
2034                    for (StartTag tag : tags) {
2035                            String targetUri = tag.getAttributeValue("href");
2036    
2037                            if (Validator.isNotNull(targetUri)) {
2038                                    try {
2039                                            LinkbackProducerUtil.sendPingback(sourceUri, targetUri);
2040                                    }
2041                                    catch (Exception e) {
2042                                            _log.error("Error while sending pingback " + targetUri, e);
2043                                    }
2044                            }
2045                    }
2046            }
2047    
2048            protected void pingTrackbacks(
2049                            BlogsEntry entry, String[] trackbacks, boolean pingOldTrackbacks,
2050                            ServiceContext serviceContext)
2051                    throws PortalException {
2052    
2053                    if (!PropsValues.BLOGS_TRACKBACK_ENABLED ||
2054                            !entry.isAllowTrackbacks() || !entry.isApproved()) {
2055    
2056                            return;
2057                    }
2058    
2059                    HttpServletRequest request = serviceContext.getRequest();
2060    
2061                    if (request == null) {
2062                            return;
2063                    }
2064    
2065                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
2066                            WebKeys.THEME_DISPLAY);
2067    
2068                    String layoutFullURL = PortalUtil.getLayoutFullURL(themeDisplay);
2069    
2070                    if (Validator.isNull(layoutFullURL)) {
2071                            return;
2072                    }
2073    
2074                    Map<String, String> parts = new HashMap<>();
2075    
2076                    String excerpt = StringUtil.shorten(
2077                            HtmlUtil.extractText(entry.getContent()),
2078                            PropsValues.BLOGS_LINKBACK_EXCERPT_LENGTH);
2079                    String url =
2080                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/" +
2081                                    entry.getUrlTitle();
2082    
2083                    parts.put("title", entry.getTitle());
2084                    parts.put("excerpt", excerpt);
2085                    parts.put("url", url);
2086                    parts.put("blog_name", entry.getUserName());
2087    
2088                    Set<String> trackbacksSet = null;
2089    
2090                    if (ArrayUtil.isNotEmpty(trackbacks)) {
2091                            trackbacksSet = SetUtil.fromArray(trackbacks);
2092                    }
2093                    else {
2094                            trackbacksSet = new HashSet<>();
2095                    }
2096    
2097                    if (pingOldTrackbacks) {
2098                            trackbacksSet.addAll(
2099                                    SetUtil.fromArray(StringUtil.split(entry.getTrackbacks())));
2100    
2101                            entry.setTrackbacks(StringPool.BLANK);
2102    
2103                            blogsEntryPersistence.update(entry);
2104                    }
2105    
2106                    Set<String> oldTrackbacks = SetUtil.fromArray(
2107                            StringUtil.split(entry.getTrackbacks()));
2108    
2109                    Set<String> validTrackbacks = new HashSet<>();
2110    
2111                    for (String trackback : trackbacksSet) {
2112                            if (oldTrackbacks.contains(trackback)) {
2113                                    continue;
2114                            }
2115    
2116                            try {
2117                                    if (LinkbackProducerUtil.sendTrackback(trackback, parts)) {
2118                                            validTrackbacks.add(trackback);
2119                                    }
2120                            }
2121                            catch (Exception e) {
2122                                    _log.error("Error while sending trackback at " + trackback, e);
2123                            }
2124                    }
2125    
2126                    if (!validTrackbacks.isEmpty()) {
2127                            String newTrackbacks = StringUtil.merge(validTrackbacks);
2128    
2129                            if (Validator.isNotNull(entry.getTrackbacks())) {
2130                                    newTrackbacks += StringPool.COMMA + entry.getTrackbacks();
2131                            }
2132    
2133                            entry.setTrackbacks(newTrackbacks);
2134    
2135                            blogsEntryPersistence.update(entry);
2136                    }
2137            }
2138    
2139            protected BlogsEntry startWorkflowInstance(
2140                            long userId, BlogsEntry entry, ServiceContext serviceContext)
2141                    throws PortalException {
2142    
2143                    Map<String, Serializable> workflowContext = new HashMap<>();
2144    
2145                    workflowContext.put(
2146                            WorkflowConstants.CONTEXT_URL, getEntryURL(entry, serviceContext));
2147    
2148                    String userPortraitURL = StringPool.BLANK;
2149                    String userURL = StringPool.BLANK;
2150    
2151                    if (serviceContext.getThemeDisplay() != null) {
2152                            User user = userPersistence.findByPrimaryKey(userId);
2153    
2154                            userPortraitURL = user.getPortraitURL(
2155                                    serviceContext.getThemeDisplay());
2156                            userURL = user.getDisplayURL(serviceContext.getThemeDisplay());
2157                    }
2158    
2159                    workflowContext.put(
2160                            WorkflowConstants.CONTEXT_USER_PORTRAIT_URL, userPortraitURL);
2161                    workflowContext.put(WorkflowConstants.CONTEXT_USER_URL, userURL);
2162    
2163                    return WorkflowHandlerRegistryUtil.startWorkflowInstance(
2164                            entry.getCompanyId(), entry.getGroupId(), userId,
2165                            BlogsEntry.class.getName(), entry.getEntryId(), entry,
2166                            serviceContext, workflowContext);
2167            }
2168    
2169            protected void validate(long smallImageFileEntryId) throws PortalException {
2170                    String[] imageExtensions = PrefsPropsUtil.getStringArray(
2171                            PropsKeys.BLOGS_IMAGE_EXTENSIONS, StringPool.COMMA);
2172    
2173                    if (smallImageFileEntryId != 0) {
2174                            FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
2175                                    smallImageFileEntryId);
2176    
2177                            boolean validSmallImageExtension = false;
2178    
2179                            for (String _imageExtension : imageExtensions) {
2180                                    if (StringPool.STAR.equals(_imageExtension) ||
2181                                            _imageExtension.equals(
2182                                                    StringPool.PERIOD + fileEntry.getExtension())) {
2183    
2184                                            validSmallImageExtension = true;
2185    
2186                                            break;
2187                                    }
2188                            }
2189    
2190                            if (!validSmallImageExtension) {
2191                                    throw new EntrySmallImageNameException(
2192                                            "Invalid small image for file entry " +
2193                                                    smallImageFileEntryId);
2194                            }
2195    
2196                            long smallImageMaxSize = PrefsPropsUtil.getLong(
2197                                    PropsKeys.BLOGS_IMAGE_SMALL_MAX_SIZE);
2198    
2199                            if ((smallImageMaxSize > 0) &&
2200                                    (fileEntry.getSize() > smallImageMaxSize)) {
2201    
2202                                    throw new EntrySmallImageSizeException();
2203                            }
2204                    }
2205            }
2206    
2207            protected void validate(String title, String content)
2208                    throws PortalException {
2209    
2210                    if (Validator.isNull(title)) {
2211                            throw new EntryTitleException("Title is null");
2212                    }
2213    
2214                    int titleMaxLength = ModelHintsUtil.getMaxLength(
2215                            BlogsEntry.class.getName(), "title");
2216    
2217                    if (title.length() > titleMaxLength) {
2218                            throw new EntryTitleException(
2219                                    "Title has more than " + titleMaxLength + " characters");
2220                    }
2221    
2222                    if (Validator.isNull(content)) {
2223                            throw new EntryContentException("Content is null");
2224                    }
2225    
2226                    int contentMaxLength = ModelHintsUtil.getMaxLength(
2227                            BlogsEntry.class.getName(), "content");
2228    
2229                    if (content.length() > contentMaxLength) {
2230                            throw new EntryContentException(
2231                                    "Content has more than " + contentMaxLength + " characters");
2232                    }
2233            }
2234    
2235            @BeanReference(type = CommentManager.class)
2236            protected CommentManager commentManager;
2237    
2238            private static final Log _log = LogFactoryUtil.getLog(
2239                    BlogsEntryLocalServiceImpl.class);
2240    
2241    }