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