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             * @throws PortalException if a user with the primary key could not be found
1021             *         or if the blogs entry owner's social activity counter could not
1022             *         be updated
1023             */
1024            @Indexable(type = IndexableType.REINDEX)
1025            @Override
1026            public BlogsEntry moveEntryToTrash(long userId, BlogsEntry entry)
1027                    throws PortalException {
1028    
1029                    // Entry
1030    
1031                    int oldStatus = entry.getStatus();
1032    
1033                    if (oldStatus == WorkflowConstants.STATUS_PENDING) {
1034                            entry.setStatus(WorkflowConstants.STATUS_DRAFT);
1035    
1036                            blogsEntryPersistence.update(entry);
1037                    }
1038    
1039                    entry = updateStatus(
1040                            userId, entry.getEntryId(), WorkflowConstants.STATUS_IN_TRASH,
1041                            new ServiceContext());
1042    
1043                    // Social
1044    
1045                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1046    
1047                    extraDataJSONObject.put("title", entry.getTitle());
1048    
1049                    SocialActivityManagerUtil.addActivity(
1050                            userId, entry, SocialActivityConstants.TYPE_MOVE_TO_TRASH,
1051                            extraDataJSONObject.toString(), 0);
1052    
1053                    // Workflow
1054    
1055                    if (oldStatus == WorkflowConstants.STATUS_PENDING) {
1056                            workflowInstanceLinkLocalService.deleteWorkflowInstanceLink(
1057                                    entry.getCompanyId(), entry.getGroupId(),
1058                                    BlogsEntry.class.getName(), entry.getEntryId());
1059                    }
1060    
1061                    return entry;
1062            }
1063    
1064            /**
1065             * Moves the blogs entry with the ID to the recycle bin.
1066             *
1067             * @param  userId the primary key of the user moving the blogs entry
1068             * @param  entryId the primary key of the blogs entry to be moved
1069             * @return the moved blogs entry
1070             * @throws PortalException if a user or blogs entry with the primary key
1071             *         could not be found or if the blogs entry owner's social activity
1072             *         counter could not be updated
1073             */
1074            @Override
1075            public BlogsEntry moveEntryToTrash(long userId, long entryId)
1076                    throws PortalException {
1077    
1078                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
1079    
1080                    return blogsEntryLocalService.moveEntryToTrash(userId, entry);
1081            }
1082    
1083            /**
1084             * Restores the blogs entry with the ID from the recycle bin. Social
1085             * activity counters for this entry get activated.
1086             *
1087             * @param  userId the primary key of the user restoring the blogs entry
1088             * @param  entryId the primary key of the blogs entry to be restored
1089             * @return the restored blogs entry from the recycle bin
1090             * @throws PortalException if a user or blogs entry with the primary key
1091             *         could not be found or if the blogs entry owner's social activity
1092             *         counter could not be updated
1093             */
1094            @Indexable(type = IndexableType.REINDEX)
1095            @Override
1096            public BlogsEntry restoreEntryFromTrash(long userId, long entryId)
1097                    throws PortalException {
1098    
1099                    // Entry
1100    
1101                    TrashEntry trashEntry = trashEntryLocalService.getEntry(
1102                            BlogsEntry.class.getName(), entryId);
1103    
1104                    BlogsEntry entry = updateStatus(
1105                            userId, entryId, trashEntry.getStatus(), new ServiceContext());
1106    
1107                    // Social
1108    
1109                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1110    
1111                    extraDataJSONObject.put("title", entry.getTitle());
1112    
1113                    SocialActivityManagerUtil.addActivity(
1114                            userId, entry, SocialActivityConstants.TYPE_RESTORE_FROM_TRASH,
1115                            extraDataJSONObject.toString(), 0);
1116    
1117                    return entry;
1118            }
1119    
1120            @Override
1121            public void subscribe(long userId, long groupId) throws PortalException {
1122                    subscriptionLocalService.addSubscription(
1123                            userId, groupId, BlogsEntry.class.getName(), groupId);
1124            }
1125    
1126            @Override
1127            public void unsubscribe(long userId, long groupId) throws PortalException {
1128                    subscriptionLocalService.deleteSubscription(
1129                            userId, BlogsEntry.class.getName(), groupId);
1130            }
1131    
1132            @Override
1133            public void updateAsset(
1134                            long userId, BlogsEntry entry, long[] assetCategoryIds,
1135                            String[] assetTagNames, long[] assetLinkEntryIds)
1136                    throws PortalException {
1137    
1138                    boolean visible = false;
1139    
1140                    if (entry.isApproved()) {
1141                            visible = true;
1142                    }
1143    
1144                    String summary = HtmlUtil.extractText(
1145                            StringUtil.shorten(entry.getContent(), 500));
1146    
1147                    AssetEntry assetEntry = assetEntryLocalService.updateEntry(
1148                            userId, entry.getGroupId(), entry.getCreateDate(),
1149                            entry.getModifiedDate(), BlogsEntry.class.getName(),
1150                            entry.getEntryId(), entry.getUuid(), 0, assetCategoryIds,
1151                            assetTagNames, visible, null, null, null, ContentTypes.TEXT_HTML,
1152                            entry.getTitle(), entry.getDescription(), summary, null, null, 0, 0,
1153                            null);
1154    
1155                    assetLinkLocalService.updateLinks(
1156                            userId, assetEntry.getEntryId(), assetLinkEntryIds,
1157                            AssetLinkConstants.TYPE_RELATED);
1158            }
1159    
1160            @Override
1161            public BlogsEntry updateEntry(
1162                            long userId, long entryId, String title, String content,
1163                            ServiceContext serviceContext)
1164                    throws PortalException {
1165    
1166                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
1167    
1168                    return updateEntry(
1169                            userId, entryId, title, entry.getSubtitle(), entry.getDescription(),
1170                            content, entry.getDisplayDate(), entry.getAllowPingbacks(),
1171                            entry.getAllowTrackbacks(), StringUtil.split(entry.getTrackbacks()),
1172                            StringPool.BLANK, null, null, serviceContext);
1173            }
1174    
1175            /**
1176             * @deprecated As of 7.0.0, replaced by {@link #updateEntry(long, long,
1177             *             String, String, String, String, int, int, int, int, int,
1178             *             boolean, boolean, String[], String, ImageSelector,
1179             *             ImageSelector, ServiceContext)}
1180             */
1181            @Deprecated
1182            @Override
1183            public BlogsEntry updateEntry(
1184                            long userId, long entryId, String title, String description,
1185                            String content, int displayDateMonth, int displayDateDay,
1186                            int displayDateYear, int displayDateHour, int displayDateMinute,
1187                            boolean allowPingbacks, boolean allowTrackbacks,
1188                            String[] trackbacks, boolean smallImage, String smallImageURL,
1189                            String smallImageFileName, InputStream smallImageInputStream,
1190                            ServiceContext serviceContext)
1191                    throws PortalException {
1192    
1193                    ImageSelector coverImageImageSelector = null;
1194                    ImageSelector smallImageImageSelector = null;
1195    
1196                    if (smallImage) {
1197                            if (Validator.isNotNull(smallImageFileName) &&
1198                                    (smallImageInputStream != null)) {
1199    
1200                                    FileEntry tempFileEntry = TempFileEntryUtil.addTempFileEntry(
1201                                            serviceContext.getScopeGroupId(), userId,
1202                                            BlogsEntry.class.getName(), smallImageFileName,
1203                                            smallImageInputStream,
1204                                            MimeTypesUtil.getContentType(smallImageFileName));
1205    
1206                                    smallImageImageSelector = new ImageSelector(
1207                                            tempFileEntry.getFileEntryId(), smallImageURL, null);
1208                            }
1209                    }
1210                    else {
1211                            smallImageImageSelector = new ImageSelector(0);
1212                    }
1213    
1214                    return updateEntry(
1215                            userId, entryId, title, StringPool.BLANK, description, content,
1216                            displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
1217                            displayDateMinute, allowPingbacks, allowTrackbacks, trackbacks,
1218                            StringPool.BLANK, coverImageImageSelector, smallImageImageSelector,
1219                            serviceContext);
1220            }
1221    
1222            @Indexable(type = IndexableType.REINDEX)
1223            @Override
1224            public BlogsEntry updateEntry(
1225                            long userId, long entryId, String title, String subtitle,
1226                            String description, String content, Date displayDate,
1227                            boolean allowPingbacks, boolean allowTrackbacks,
1228                            String[] trackbacks, String coverImageCaption,
1229                            ImageSelector coverImageImageSelector,
1230                            ImageSelector smallImageImageSelector,
1231                            ServiceContext serviceContext)
1232                    throws PortalException {
1233    
1234                    // Entry
1235    
1236                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
1237    
1238                    validate(title, content);
1239    
1240                    String oldUrlTitle = entry.getUrlTitle();
1241    
1242                    entry.setTitle(title);
1243                    entry.setSubtitle(subtitle);
1244                    entry.setUrlTitle(
1245                            getUniqueUrlTitle(entryId, title, oldUrlTitle, serviceContext));
1246                    entry.setDescription(description);
1247                    entry.setContent(content);
1248                    entry.setDisplayDate(displayDate);
1249                    entry.setAllowPingbacks(allowPingbacks);
1250                    entry.setAllowTrackbacks(allowTrackbacks);
1251    
1252                    if (entry.isPending() || entry.isDraft()) {
1253                    }
1254                    else {
1255                            entry.setStatus(WorkflowConstants.STATUS_DRAFT);
1256                    }
1257    
1258                    entry.setExpandoBridgeAttributes(serviceContext);
1259    
1260                    blogsEntryPersistence.update(entry);
1261    
1262                    // Resources
1263    
1264                    if ((serviceContext.getGroupPermissions() != null) ||
1265                            (serviceContext.getGuestPermissions() != null)) {
1266    
1267                            updateEntryResources(entry, serviceContext.getModelPermissions());
1268                    }
1269    
1270                    // Asset
1271    
1272                    updateAsset(
1273                            userId, entry, serviceContext.getAssetCategoryIds(),
1274                            serviceContext.getAssetTagNames(),
1275                            serviceContext.getAssetLinkEntryIds());
1276    
1277                    // Images
1278    
1279                    long coverImageFileEntryId = entry.getCoverImageFileEntryId();
1280                    String coverImageURL = entry.getCoverImageURL();
1281    
1282                    long deletePreviousCoverImageFileEntryId = 0;
1283    
1284                    if (coverImageImageSelector != null) {
1285                            coverImageFileEntryId = coverImageImageSelector.getImageId();
1286                            coverImageURL = coverImageImageSelector.getImageURL();
1287    
1288                            if (coverImageImageSelector.getImageId() == 0) {
1289                                    if (entry.getCoverImageFileEntryId() != 0) {
1290                                            deletePreviousCoverImageFileEntryId =
1291                                                    entry.getCoverImageFileEntryId();
1292                                    }
1293                            }
1294                            else if (coverImageImageSelector.getImageId() !=
1295                                                    entry.getCoverImageFileEntryId()) {
1296    
1297                                    if (entry.getCoverImageFileEntryId() != 0) {
1298                                            deletePreviousCoverImageFileEntryId =
1299                                                    entry.getCoverImageFileEntryId();
1300                                    }
1301    
1302                                    if (coverImageImageSelector.getImageId() != 0) {
1303                                            coverImageFileEntryId = addCoverImageFileEntry(
1304                                                    userId, entry.getGroupId(), entryId,
1305                                                    coverImageImageSelector);
1306                                    }
1307                            }
1308                    }
1309    
1310                    boolean smallImage = entry.isSmallImage();
1311                    long smallImageFileEntryId = entry.getSmallImageFileEntryId();
1312                    String smallImageURL = entry.getSmallImageURL();
1313    
1314                    long deletePreviousSmallImageFileEntryId = 0;
1315    
1316                    if (smallImageImageSelector != null) {
1317                            smallImage = !smallImageImageSelector.isRemoveSmallImage();
1318                            smallImageFileEntryId = smallImageImageSelector.getImageId();
1319                            smallImageURL = smallImageImageSelector.getImageURL();
1320    
1321                            if (smallImageImageSelector.getImageId() == 0) {
1322                                    if (entry.getSmallImageFileEntryId() != 0) {
1323                                            deletePreviousSmallImageFileEntryId =
1324                                                    entry.getSmallImageFileEntryId();
1325                                    }
1326                            }
1327                            else if (smallImageImageSelector.getImageId() !=
1328                                                    entry.getSmallImageFileEntryId()) {
1329    
1330                                    if (entry.getSmallImageFileEntryId() != 0) {
1331                                            deletePreviousSmallImageFileEntryId =
1332                                                    entry.getSmallImageFileEntryId();
1333                                    }
1334    
1335                                    if (smallImageImageSelector.getImageId() != 0) {
1336                                            smallImageFileEntryId = addSmallImageFileEntry(
1337                                                    userId, entry.getGroupId(), entry.getEntryId(),
1338                                                    smallImageImageSelector);
1339                                    }
1340                            }
1341                    }
1342    
1343                    validate(smallImageFileEntryId);
1344    
1345                    entry.setCoverImageCaption(coverImageCaption);
1346                    entry.setCoverImageFileEntryId(coverImageFileEntryId);
1347                    entry.setCoverImageURL(coverImageURL);
1348                    entry.setSmallImage(smallImage);
1349                    entry.setSmallImageFileEntryId(smallImageFileEntryId);
1350                    entry.setSmallImageURL(smallImageURL);
1351    
1352                    blogsEntryPersistence.update(entry);
1353    
1354                    // Workflow
1355    
1356                    boolean pingOldTrackbacks = false;
1357    
1358                    if (!oldUrlTitle.equals(entry.getUrlTitle())) {
1359                            pingOldTrackbacks = true;
1360                    }
1361    
1362                    serviceContext.setAttribute(
1363                            "pingOldTrackbacks", String.valueOf(pingOldTrackbacks));
1364    
1365                    if (ArrayUtil.isNotEmpty(trackbacks)) {
1366                            serviceContext.setAttribute("trackbacks", trackbacks);
1367                    }
1368                    else {
1369                            serviceContext.setAttribute("trackbacks", null);
1370                    }
1371    
1372                    entry = startWorkflowInstance(userId, entry, serviceContext);
1373    
1374                    if (deletePreviousCoverImageFileEntryId != 0) {
1375                            PortletFileRepositoryUtil.deletePortletFileEntry(
1376                                    deletePreviousCoverImageFileEntryId);
1377                    }
1378    
1379                    if (deletePreviousSmallImageFileEntryId != 0) {
1380                            PortletFileRepositoryUtil.deletePortletFileEntry(
1381                                    deletePreviousSmallImageFileEntryId);
1382                    }
1383    
1384                    if ((coverImageImageSelector != null) &&
1385                            (coverImageImageSelector.getImageId() !=
1386                                    entry.getCoverImageFileEntryId())) {
1387    
1388                            deleteTempImageSelectorImage(coverImageImageSelector);
1389                    }
1390    
1391                    if ((smallImageImageSelector != null) &&
1392                            (smallImageImageSelector.getImageId() !=
1393                                    entry.getCoverImageFileEntryId())) {
1394    
1395                            deleteTempImageSelectorImage(smallImageImageSelector);
1396                    }
1397    
1398                    return entry;
1399            }
1400    
1401            @Override
1402            public BlogsEntry updateEntry(
1403                            long userId, long entryId, String title, String subtitle,
1404                            String description, String content, int displayDateMonth,
1405                            int displayDateDay, int displayDateYear, int displayDateHour,
1406                            int displayDateMinute, boolean allowPingbacks,
1407                            boolean allowTrackbacks, String[] trackbacks,
1408                            String coverImageCaption, ImageSelector coverImageImageSelector,
1409                            ImageSelector smallImageImageSelector,
1410                            ServiceContext serviceContext)
1411                    throws PortalException {
1412    
1413                    User user = userPersistence.findByPrimaryKey(userId);
1414    
1415                    Date displayDate = PortalUtil.getDate(
1416                            displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
1417                            displayDateMinute, user.getTimeZone(),
1418                            EntryDisplayDateException.class);
1419    
1420                    return updateEntry(
1421                            userId, entryId, title, subtitle, description, content, displayDate,
1422                            allowPingbacks, allowTrackbacks, trackbacks, coverImageCaption,
1423                            coverImageImageSelector, smallImageImageSelector, serviceContext);
1424            }
1425    
1426            @Override
1427            public void updateEntryResources(
1428                            BlogsEntry entry, ModelPermissions modelPermissions)
1429                    throws PortalException {
1430    
1431                    resourceLocalService.updateResources(
1432                            entry.getCompanyId(), entry.getGroupId(),
1433                            BlogsEntry.class.getName(), entry.getEntryId(), modelPermissions);
1434            }
1435    
1436            @Override
1437            public void updateEntryResources(
1438                            BlogsEntry entry, String[] groupPermissions,
1439                            String[] guestPermissions)
1440                    throws PortalException {
1441    
1442                    resourceLocalService.updateResources(
1443                            entry.getCompanyId(), entry.getGroupId(),
1444                            BlogsEntry.class.getName(), entry.getEntryId(), groupPermissions,
1445                            guestPermissions);
1446            }
1447    
1448            /**
1449             * @deprecated As of 7.0.0, replaced by {@link #updateStatus(long, long,
1450             *             int, ServiceContext, Map)}
1451             */
1452            @Deprecated
1453            @Override
1454            public BlogsEntry updateStatus(
1455                            long userId, long entryId, int status,
1456                            ServiceContext serviceContext)
1457                    throws PortalException {
1458    
1459                    return updateStatus(
1460                            userId, entryId, status, serviceContext,
1461                            new HashMap<String, Serializable>());
1462            }
1463    
1464            @Indexable(type = IndexableType.REINDEX)
1465            @Override
1466            public BlogsEntry updateStatus(
1467                            long userId, long entryId, int status,
1468                            ServiceContext serviceContext,
1469                            Map<String, Serializable> workflowContext)
1470                    throws PortalException {
1471    
1472                    // Entry
1473    
1474                    User user = userPersistence.findByPrimaryKey(userId);
1475                    Date now = new Date();
1476    
1477                    BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
1478    
1479                    int oldStatus = entry.getStatus();
1480    
1481                    if ((status == WorkflowConstants.STATUS_APPROVED) &&
1482                            now.before(entry.getDisplayDate())) {
1483    
1484                            status = WorkflowConstants.STATUS_SCHEDULED;
1485                    }
1486    
1487                    entry.setStatus(status);
1488                    entry.setStatusByUserId(user.getUserId());
1489                    entry.setStatusByUserName(user.getFullName());
1490                    entry.setStatusDate(serviceContext.getModifiedDate(now));
1491    
1492                    blogsEntryPersistence.update(entry);
1493    
1494                    // Statistics
1495    
1496                    blogsStatsUserLocalService.updateStatsUser(
1497                            entry.getGroupId(), entry.getUserId(), entry.getDisplayDate());
1498    
1499                    AssetEntry assetEntry = assetEntryLocalService.fetchEntry(
1500                            BlogsEntry.class.getName(), entryId);
1501    
1502                    if ((assetEntry == null) || (assetEntry.getPublishDate() == null)) {
1503                            serviceContext.setCommand(Constants.ADD);
1504                    }
1505    
1506                    JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject();
1507    
1508                    extraDataJSONObject.put("title", entry.getTitle());
1509    
1510                    if (status == WorkflowConstants.STATUS_APPROVED) {
1511    
1512                            // Asset
1513    
1514                            assetEntryLocalService.updateEntry(
1515                                    BlogsEntry.class.getName(), entryId, entry.getDisplayDate(),
1516                                    true);
1517    
1518                            // Social
1519    
1520                            if ((oldStatus != WorkflowConstants.STATUS_IN_TRASH) &&
1521                                    (oldStatus != WorkflowConstants.STATUS_SCHEDULED)) {
1522    
1523                                    if (serviceContext.isCommandUpdate()) {
1524                                            SocialActivityManagerUtil.addActivity(
1525                                                    user.getUserId(), entry, BlogsActivityKeys.UPDATE_ENTRY,
1526                                                    extraDataJSONObject.toString(), 0);
1527                                    }
1528                                    else {
1529                                            SocialActivityManagerUtil.addUniqueActivity(
1530                                                    user.getUserId(), entry, BlogsActivityKeys.ADD_ENTRY,
1531                                                    extraDataJSONObject.toString(), 0);
1532                                    }
1533                            }
1534    
1535                            // Trash
1536    
1537                            if (oldStatus == WorkflowConstants.STATUS_IN_TRASH) {
1538                                    if (PropsValues.BLOGS_ENTRY_COMMENTS_ENABLED) {
1539                                            commentManager.restoreDiscussionFromTrash(
1540                                                    BlogsEntry.class.getName(), entryId);
1541                                    }
1542    
1543                                    trashEntryLocalService.deleteEntry(
1544                                            BlogsEntry.class.getName(), entryId);
1545                            }
1546    
1547                            if (oldStatus != WorkflowConstants.STATUS_IN_TRASH) {
1548    
1549                                    // Subscriptions
1550    
1551                                    notifySubscribers(
1552                                            userId, entry, serviceContext, workflowContext);
1553    
1554                                    // Ping
1555    
1556                                    String[] trackbacks = (String[])serviceContext.getAttribute(
1557                                            "trackbacks");
1558                                    Boolean pingOldTrackbacks = ParamUtil.getBoolean(
1559                                            serviceContext, "pingOldTrackbacks");
1560    
1561                                    pingGoogle(entry, serviceContext);
1562                                    pingPingback(entry, serviceContext);
1563                                    pingTrackbacks(
1564                                            entry, trackbacks, pingOldTrackbacks, serviceContext);
1565                            }
1566                    }
1567                    else {
1568    
1569                            // Asset
1570    
1571                            assetEntryLocalService.updateVisible(
1572                                    BlogsEntry.class.getName(), entryId, false);
1573    
1574                            // Social
1575    
1576                            if ((status == WorkflowConstants.STATUS_SCHEDULED) &&
1577                                    (oldStatus != WorkflowConstants.STATUS_IN_TRASH)) {
1578    
1579                                    if (serviceContext.isCommandUpdate()) {
1580                                            SocialActivityManagerUtil.addActivity(
1581                                                    user.getUserId(), entry, BlogsActivityKeys.UPDATE_ENTRY,
1582                                                    extraDataJSONObject.toString(), 0);
1583                                    }
1584                                    else {
1585                                            SocialActivityManagerUtil.addUniqueActivity(
1586                                                    user.getUserId(), entry, BlogsActivityKeys.ADD_ENTRY,
1587                                                    extraDataJSONObject.toString(), 0);
1588                                    }
1589                            }
1590    
1591                            // Trash
1592    
1593                            if (status == WorkflowConstants.STATUS_IN_TRASH) {
1594                                    if (PropsValues.BLOGS_ENTRY_COMMENTS_ENABLED) {
1595                                            commentManager.moveDiscussionToTrash(
1596                                                    BlogsEntry.class.getName(), entryId);
1597                                    }
1598    
1599                                    trashEntryLocalService.addTrashEntry(
1600                                            userId, entry.getGroupId(), BlogsEntry.class.getName(),
1601                                            entry.getEntryId(), entry.getUuid(), null, oldStatus, null,
1602                                            null);
1603                            }
1604                            else if (oldStatus == WorkflowConstants.STATUS_IN_TRASH) {
1605                                    if (PropsValues.BLOGS_ENTRY_COMMENTS_ENABLED) {
1606                                            commentManager.restoreDiscussionFromTrash(
1607                                                    BlogsEntry.class.getName(), entryId);
1608                                    }
1609    
1610                                    trashEntryLocalService.deleteEntry(
1611                                            BlogsEntry.class.getName(), entryId);
1612                            }
1613                    }
1614    
1615                    return entry;
1616            }
1617    
1618            protected long addCoverImageFileEntry(
1619                            long userId, long groupId, long entryId,
1620                            ImageSelector imageSelector)
1621                    throws PortalException {
1622    
1623                    FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
1624                            imageSelector.getImageId());
1625    
1626                    addOriginalImageFileEntry(userId, groupId, entryId, fileEntry);
1627    
1628                    File file = null;
1629    
1630                    try {
1631                            byte[] bytes = imageSelector.getCroppedImageBytes();
1632    
1633                            if (bytes == null) {
1634                                    throw new EntryCoverImageCropException();
1635                            }
1636    
1637                            file = FileUtil.createTempFile(bytes);
1638    
1639                            Folder folder = addCoverImageFolder(userId, groupId);
1640    
1641                            return addProcessedImageFileEntry(
1642                                    userId, groupId, entryId, folder.getFolderId(), imageSelector,
1643                                    file);
1644                    }
1645                    catch (IOException ioe) {
1646                            throw new EntryCoverImageCropException();
1647                    }
1648                    finally {
1649                            FileUtil.delete(file);
1650                    }
1651            }
1652    
1653            protected Folder addCoverImageFolder(long userId, long groupId)
1654                    throws PortalException {
1655    
1656                    return doAddFolder(userId, groupId, _COVER_IMAGE_FOLDER_NAME);
1657            }
1658    
1659            protected void addDiscussion(BlogsEntry entry, long userId, long groupId)
1660                    throws PortalException {
1661    
1662                    if (PropsValues.BLOGS_ENTRY_COMMENTS_ENABLED) {
1663                            commentManager.addDiscussion(
1664                                    userId, groupId, BlogsEntry.class.getName(), entry.getEntryId(),
1665                                    entry.getUserName());
1666                    }
1667            }
1668    
1669            protected long addOriginalImageFileEntry(
1670                            long userId, long groupId, long entryId, FileEntry fileEntry)
1671                    throws PortalException {
1672    
1673                    if (!fileEntry.isRepositoryCapabilityProvided(
1674                                    TemporaryFileEntriesCapability.class)) {
1675    
1676                            return fileEntry.getFileEntryId();
1677                    }
1678    
1679                    BlogsEntryAttachmentFileEntryHelper
1680                            blogsEntryAttachmentFileEntryHelper =
1681                                    new BlogsEntryAttachmentFileEntryHelper();
1682    
1683                    Folder folder = addAttachmentsFolder(userId, groupId);
1684    
1685                    FileEntry originalFileEntry =
1686                            blogsEntryAttachmentFileEntryHelper.
1687                                    addBlogsEntryAttachmentFileEntry(
1688                                            groupId, userId, entryId, folder.getFolderId(),
1689                                            fileEntry.getTitle(), fileEntry.getMimeType(),
1690                                            fileEntry.getContentStream());
1691    
1692                    return originalFileEntry.getFileEntryId();
1693            }
1694    
1695            protected long addProcessedImageFileEntry(
1696                            long userId, long groupId, long entryId, long folderId,
1697                            ImageSelector imageSelector, File file)
1698                    throws PortalException {
1699    
1700                    String title = imageSelector.getTitle();
1701    
1702                    if (Validator.isNull(title)) {
1703                            title = StringUtil.randomString() + "_processedImage_" + entryId;
1704                    }
1705    
1706                    BlogsEntryAttachmentFileEntryHelper
1707                            blogsEntryAttachmentFileEntryHelper =
1708                                    new BlogsEntryAttachmentFileEntryHelper();
1709    
1710                    FileEntry processedImageFileEntry =
1711                            blogsEntryAttachmentFileEntryHelper.
1712                                    addBlogsEntryAttachmentFileEntry(
1713                                            groupId, userId, entryId, folderId, title,
1714                                            imageSelector.getMimeType(), file);
1715    
1716                    return processedImageFileEntry.getFileEntryId();
1717            }
1718    
1719            protected long addSmallImageFileEntry(
1720                            long userId, long groupId, long entryId,
1721                            ImageSelector imageSelector)
1722                    throws PortalException {
1723    
1724                    FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
1725                            imageSelector.getImageId());
1726    
1727                    addOriginalImageFileEntry(userId, groupId, entryId, fileEntry);
1728    
1729                    File file = null;
1730    
1731                    try {
1732                            ImageBag imageBag = ImageToolUtil.read(
1733                                    fileEntry.getContentStream());
1734    
1735                            RenderedImage renderedImage = imageBag.getRenderedImage();
1736    
1737                            BlogsGroupServiceSettings blogsGroupServiceSettings =
1738                                    BlogsGroupServiceSettings.getInstance(groupId);
1739    
1740                            renderedImage = ImageToolUtil.scale(
1741                                    renderedImage, blogsGroupServiceSettings.getSmallImageWidth());
1742    
1743                            byte[] bytes = ImageToolUtil.getBytes(
1744                                    renderedImage, imageBag.getType());
1745    
1746                            if (bytes == null) {
1747                                    throw new EntrySmallImageScaleException();
1748                            }
1749    
1750                            file = FileUtil.createTempFile(bytes);
1751    
1752                            Folder folder = addSmallImageFolder(userId, groupId);
1753    
1754                            return addProcessedImageFileEntry(
1755                                    userId, groupId, entryId, folder.getFolderId(), imageSelector,
1756                                    file);
1757                    }
1758                    catch (IOException ioe) {
1759                            throw new EntrySmallImageScaleException();
1760                    }
1761                    finally {
1762                            FileUtil.delete(file);
1763                    }
1764            }
1765    
1766            protected Folder addSmallImageFolder(long userId, long groupId)
1767                    throws PortalException {
1768    
1769                    return doAddFolder(userId, groupId, _SMALL_IMAGE_FOLDER_NAME);
1770            }
1771    
1772            protected void deleteDiscussion(BlogsEntry entry) throws PortalException {
1773                    commentManager.deleteDiscussion(
1774                            BlogsEntry.class.getName(), entry.getEntryId());
1775            }
1776    
1777            protected void deleteTempImageSelectorImage(ImageSelector imageSelector)
1778                    throws PortalException {
1779    
1780                    if ((imageSelector == null) || (imageSelector.getImageId() == 0)) {
1781                            return;
1782                    }
1783    
1784                    long imageSelectorImageId = imageSelector.getImageId();
1785    
1786                    FileEntry imageSelectorImageFileEntry =
1787                            PortletFileRepositoryUtil.getPortletFileEntry(imageSelectorImageId);
1788    
1789                    if (imageSelectorImageFileEntry.isRepositoryCapabilityProvided(
1790                                    TemporaryFileEntriesCapability.class)) {
1791    
1792                            PortletFileRepositoryUtil.deletePortletFileEntry(
1793                                    imageSelector.getImageId());
1794                    }
1795            }
1796    
1797            protected Folder doAddFolder(long userId, long groupId, String folderName)
1798                    throws PortalException {
1799    
1800                    ServiceContext serviceContext = new ServiceContext();
1801    
1802                    serviceContext.setAddGroupPermissions(true);
1803                    serviceContext.setAddGuestPermissions(true);
1804    
1805                    Repository repository = PortletFileRepositoryUtil.addPortletRepository(
1806                            groupId, BlogsConstants.SERVICE_NAME, serviceContext);
1807    
1808                    Folder folder = PortletFileRepositoryUtil.addPortletFolder(
1809                            userId, repository.getRepositoryId(),
1810                            DLFolderConstants.DEFAULT_PARENT_FOLDER_ID, folderName,
1811                            serviceContext);
1812    
1813                    return folder;
1814            }
1815    
1816            protected String getEntryURL(
1817                            BlogsEntry entry, ServiceContext serviceContext)
1818                    throws PortalException {
1819    
1820                    String entryURL = GetterUtil.getString(
1821                            serviceContext.getAttribute("entryURL"));
1822    
1823                    if (Validator.isNotNull(entryURL)) {
1824                            return entryURL;
1825                    }
1826    
1827                    HttpServletRequest request = serviceContext.getRequest();
1828    
1829                    if (request == null) {
1830                            return StringPool.BLANK;
1831                    }
1832    
1833                    String portletId = PortletProviderUtil.getPortletId(
1834                            BlogsEntry.class.getName(), PortletProvider.Action.VIEW);
1835    
1836                    if (Validator.isNotNull(portletId)) {
1837                            String layoutURL = LayoutURLUtil.getLayoutURL(
1838                                    entry.getGroupId(), portletId, serviceContext);
1839    
1840                            if (Validator.isNotNull(layoutURL)) {
1841                                    return layoutURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs" +
1842                                            StringPool.SLASH + entry.getEntryId();
1843                            }
1844                    }
1845    
1846                    portletId = PortletProviderUtil.getPortletId(
1847                            BlogsEntry.class.getName(), PortletProvider.Action.MANAGE);
1848    
1849                    if (Validator.isNull(portletId)) {
1850                            return StringPool.BLANK;
1851                    }
1852    
1853                    PortletURL portletURL = PortalUtil.getControlPanelPortletURL(
1854                            request, portletId, 0, PortletRequest.RENDER_PHASE);
1855    
1856                    portletURL.setParameter("mvcRenderCommandName", "/blogs/view_entry");
1857                    portletURL.setParameter("entryId", String.valueOf(entry.getEntryId()));
1858    
1859                    return portletURL.toString();
1860            }
1861    
1862            protected String getUniqueUrlTitle(
1863                    long entryId, long groupId, String title) {
1864    
1865                    String urlTitle = BlogsUtil.getUrlTitle(entryId, title);
1866    
1867                    for (int i = 1;; i++) {
1868                            BlogsEntry entry = blogsEntryPersistence.fetchByG_UT(
1869                                    groupId, urlTitle);
1870    
1871                            if ((entry == null) || (entryId == entry.getEntryId())) {
1872                                    break;
1873                            }
1874                            else {
1875                                    String suffix = StringPool.DASH + i;
1876    
1877                                    String prefix = urlTitle;
1878    
1879                                    if (urlTitle.length() > suffix.length()) {
1880                                            prefix = urlTitle.substring(
1881                                                    0, urlTitle.length() - suffix.length());
1882                                    }
1883    
1884                                    urlTitle = prefix + suffix;
1885                            }
1886                    }
1887    
1888                    return urlTitle;
1889            }
1890    
1891            protected String getUniqueUrlTitle(
1892                    long entryId, String title, String oldUrlTitle,
1893                    ServiceContext serviceContext) {
1894    
1895                    String serviceContextUrlTitle = ParamUtil.getString(
1896                            serviceContext, "urlTitle");
1897    
1898                    String urlTitle = null;
1899    
1900                    if (Validator.isNotNull(serviceContextUrlTitle)) {
1901                            urlTitle = BlogsUtil.getUrlTitle(entryId, serviceContextUrlTitle);
1902                    }
1903                    else if (Validator.isNotNull(oldUrlTitle)) {
1904                            return oldUrlTitle;
1905                    }
1906                    else {
1907                            urlTitle = getUniqueUrlTitle(
1908                                    entryId, serviceContext.getScopeGroupId(), title);
1909                    }
1910    
1911                    BlogsEntry urlTitleEntry = blogsEntryPersistence.fetchByG_UT(
1912                            serviceContext.getScopeGroupId(), urlTitle);
1913    
1914                    if ((urlTitleEntry != null) &&
1915                            (urlTitleEntry.getEntryId() != entryId)) {
1916    
1917                            urlTitle = getUniqueUrlTitle(
1918                                    entryId, serviceContext.getScopeGroupId(), urlTitle);
1919                    }
1920    
1921                    return urlTitle;
1922            }
1923    
1924            protected void notifySubscribers(
1925                            long userId, BlogsEntry entry, ServiceContext serviceContext,
1926                            Map<String, Serializable> workflowContext)
1927                    throws PortalException {
1928    
1929                    String entryURL = (String)workflowContext.get(
1930                            WorkflowConstants.CONTEXT_URL);
1931    
1932                    if (!entry.isApproved() || Validator.isNull(entryURL)) {
1933                            return;
1934                    }
1935    
1936                    BlogsGroupServiceSettings blogsGroupServiceSettings =
1937                            BlogsGroupServiceSettings.getInstance(entry.getGroupId());
1938    
1939                    boolean sendEmailEntryUpdated = GetterUtil.getBoolean(
1940                            serviceContext.getAttribute("sendEmailEntryUpdated"));
1941    
1942                    if (serviceContext.isCommandAdd() &&
1943                            blogsGroupServiceSettings.isEmailEntryAddedEnabled()) {
1944                    }
1945                    else if (sendEmailEntryUpdated && serviceContext.isCommandUpdate() &&
1946                                     blogsGroupServiceSettings.isEmailEntryUpdatedEnabled()) {
1947                    }
1948                    else {
1949                            return;
1950                    }
1951    
1952                    Group group = groupPersistence.findByPrimaryKey(entry.getGroupId());
1953    
1954                    String entryTitle = entry.getTitle();
1955    
1956                    String fromName = blogsGroupServiceSettings.getEmailFromName();
1957                    String fromAddress = blogsGroupServiceSettings.getEmailFromAddress();
1958    
1959                    LocalizedValuesMap subjectLocalizedValuesMap = null;
1960                    LocalizedValuesMap bodyLocalizedValuesMap = null;
1961    
1962                    if (serviceContext.isCommandUpdate()) {
1963                            subjectLocalizedValuesMap =
1964                                    blogsGroupServiceSettings.getEmailEntryUpdatedSubject();
1965                            bodyLocalizedValuesMap =
1966                                    blogsGroupServiceSettings.getEmailEntryUpdatedBody();
1967                    }
1968                    else {
1969                            subjectLocalizedValuesMap =
1970                                    blogsGroupServiceSettings.getEmailEntryAddedSubject();
1971                            bodyLocalizedValuesMap =
1972                                    blogsGroupServiceSettings.getEmailEntryAddedBody();
1973                    }
1974    
1975                    SubscriptionSender subscriptionSender =
1976                            new GroupSubscriptionCheckSubscriptionSender(
1977                                    BlogsPermission.RESOURCE_NAME);
1978    
1979                    subscriptionSender.setClassPK(entry.getEntryId());
1980                    subscriptionSender.setClassName(entry.getModelClassName());
1981                    subscriptionSender.setCompanyId(entry.getCompanyId());
1982                    subscriptionSender.setContextAttribute(
1983                            "[$BLOGS_ENTRY_CONTENT$]",
1984                            StringUtil.shorten(HtmlUtil.stripHtml(entry.getContent()), 500),
1985                            false);
1986                    subscriptionSender.setContextAttributes(
1987                            "[$BLOGS_ENTRY_CREATE_DATE$]",
1988                            Time.getSimpleDate(entry.getCreateDate(), "yyyy/MM/dd"),
1989                            "[$BLOGS_ENTRY_DESCRIPTION$]", entry.getDescription(),
1990                            "[$BLOGS_ENTRY_SITE_NAME$]",
1991                                    group.getDescriptiveName(serviceContext.getLocale()),
1992                            "[$BLOGS_ENTRY_STATUS_BY_USER_NAME$]", entry.getStatusByUserName(),
1993                            "[$BLOGS_ENTRY_TITLE$]", entryTitle,
1994                            "[$BLOGS_ENTRY_UPDATE_COMMENT$]",
1995                            HtmlUtil.replaceNewLine(
1996                                    GetterUtil.getString(
1997                                            serviceContext.getAttribute("emailEntryUpdatedComment"))),
1998                            "[$BLOGS_ENTRY_URL$]", entryURL,
1999                            "[$BLOGS_ENTRY_USER_PORTRAIT_URL$]",
2000                            workflowContext.get(WorkflowConstants.CONTEXT_USER_PORTRAIT_URL),
2001                            "[$BLOGS_ENTRY_USER_URL$]",
2002                            workflowContext.get(WorkflowConstants.CONTEXT_USER_URL));
2003                    subscriptionSender.setContextCreatorUserPrefix("BLOGS_ENTRY");
2004                    subscriptionSender.setCreatorUserId(entry.getUserId());
2005                    subscriptionSender.setCurrentUserId(userId);
2006                    subscriptionSender.setEntryTitle(entryTitle);
2007                    subscriptionSender.setEntryURL(entryURL);
2008                    subscriptionSender.setFrom(fromAddress, fromName);
2009                    subscriptionSender.setHtmlFormat(true);
2010    
2011                    if (bodyLocalizedValuesMap != null) {
2012                            subscriptionSender.setLocalizedBodyMap(
2013                                    LocalizationUtil.getMap(bodyLocalizedValuesMap));
2014                    }
2015    
2016                    if (subjectLocalizedValuesMap != null) {
2017                            subscriptionSender.setLocalizedSubjectMap(
2018                                    LocalizationUtil.getMap(subjectLocalizedValuesMap));
2019                    }
2020    
2021                    subscriptionSender.setMailId("blogs_entry", entry.getEntryId());
2022    
2023                    int notificationType =
2024                            UserNotificationDefinition.NOTIFICATION_TYPE_ADD_ENTRY;
2025    
2026                    if (serviceContext.isCommandUpdate()) {
2027                            notificationType =
2028                                    UserNotificationDefinition.NOTIFICATION_TYPE_UPDATE_ENTRY;
2029                    }
2030    
2031                    subscriptionSender.setNotificationType(notificationType);
2032    
2033                    String portletId = PortletProviderUtil.getPortletId(
2034                            BlogsEntry.class.getName(), PortletProvider.Action.VIEW);
2035    
2036                    subscriptionSender.setPortletId(portletId);
2037                    subscriptionSender.setReplyToAddress(fromAddress);
2038                    subscriptionSender.setScopeGroupId(entry.getGroupId());
2039                    subscriptionSender.setServiceContext(serviceContext);
2040    
2041                    subscriptionSender.addPersistedSubscribers(
2042                            BlogsEntry.class.getName(), entry.getGroupId());
2043    
2044                    subscriptionSender.addPersistedSubscribers(
2045                            BlogsEntry.class.getName(), entry.getEntryId());
2046    
2047                    subscriptionSender.flushNotificationsAsync();
2048            }
2049    
2050            protected void pingGoogle(BlogsEntry entry, ServiceContext serviceContext)
2051                    throws PortalException {
2052    
2053                    if (!PropsValues.BLOGS_PING_GOOGLE_ENABLED || !entry.isApproved()) {
2054                            return;
2055                    }
2056    
2057                    String portletId = PortletProviderUtil.getPortletId(
2058                            BlogsEntry.class.getName(), PortletProvider.Action.MANAGE);
2059    
2060                    if (Validator.isNull(portletId)) {
2061                            if (_log.isDebugEnabled()) {
2062                                    _log.debug(
2063                                            "Not pinging Google because there is no blogs portlet " +
2064                                                    "provider");
2065                            }
2066    
2067                            return;
2068                    }
2069    
2070                    String layoutFullURL = PortalUtil.getLayoutFullURL(
2071                            serviceContext.getScopeGroupId(), portletId);
2072    
2073                    if (Validator.isNull(layoutFullURL)) {
2074                            return;
2075                    }
2076    
2077                    if (layoutFullURL.contains("://localhost")) {
2078                            if (_log.isDebugEnabled()) {
2079                                    _log.debug(
2080                                            "Not pinging Google because of localhost URL " +
2081                                                    layoutFullURL);
2082                            }
2083    
2084                            return;
2085                    }
2086    
2087                    Group group = groupPersistence.findByPrimaryKey(entry.getGroupId());
2088    
2089                    StringBundler sb = new StringBundler(6);
2090    
2091                    String name = group.getDescriptiveName();
2092                    String url = layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs";
2093                    String changesURL = serviceContext.getPathMain() + "/blogs/rss";
2094    
2095                    sb.append("http://blogsearch.google.com/ping?name=");
2096                    sb.append(HttpUtil.encodeURL(name));
2097                    sb.append("&url=");
2098                    sb.append(HttpUtil.encodeURL(url));
2099                    sb.append("&changesURL=");
2100                    sb.append(HttpUtil.encodeURL(changesURL));
2101    
2102                    String location = sb.toString();
2103    
2104                    if (_log.isInfoEnabled()) {
2105                            _log.info("Pinging Google at " + location);
2106                    }
2107    
2108                    try {
2109                            String response = HttpUtil.URLtoString(sb.toString());
2110    
2111                            if (_log.isInfoEnabled()) {
2112                                    _log.info("Google ping response: " + response);
2113                            }
2114                    }
2115                    catch (IOException ioe) {
2116                            _log.error("Unable to ping Google at " + location, ioe);
2117                    }
2118            }
2119    
2120            protected void pingPingback(BlogsEntry entry, ServiceContext serviceContext)
2121                    throws PortalException {
2122    
2123                    if (!PropsValues.BLOGS_PINGBACK_ENABLED ||
2124                            !entry.isAllowPingbacks() || !entry.isApproved()) {
2125    
2126                            return;
2127                    }
2128    
2129                    HttpServletRequest request = serviceContext.getRequest();
2130    
2131                    if (request == null) {
2132                            return;
2133                    }
2134    
2135                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
2136                            WebKeys.THEME_DISPLAY);
2137    
2138                    String layoutFullURL = PortalUtil.getLayoutFullURL(themeDisplay);
2139    
2140                    if (Validator.isNull(layoutFullURL)) {
2141                            return;
2142                    }
2143    
2144                    String sourceUri =
2145                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/" +
2146                                    entry.getUrlTitle();
2147    
2148                    Source source = new Source(entry.getContent());
2149    
2150                    List<StartTag> tags = source.getAllStartTags("a");
2151    
2152                    for (StartTag tag : tags) {
2153                            String targetUri = tag.getAttributeValue("href");
2154    
2155                            if (Validator.isNotNull(targetUri)) {
2156                                    try {
2157                                            LinkbackProducerUtil.sendPingback(sourceUri, targetUri);
2158                                    }
2159                                    catch (Exception e) {
2160                                            _log.error("Error while sending pingback " + targetUri, e);
2161                                    }
2162                            }
2163                    }
2164            }
2165    
2166            protected void pingTrackbacks(
2167                            BlogsEntry entry, String[] trackbacks, boolean pingOldTrackbacks,
2168                            ServiceContext serviceContext)
2169                    throws PortalException {
2170    
2171                    if (!PropsValues.BLOGS_TRACKBACK_ENABLED ||
2172                            !entry.isAllowTrackbacks() || !entry.isApproved()) {
2173    
2174                            return;
2175                    }
2176    
2177                    HttpServletRequest request = serviceContext.getRequest();
2178    
2179                    if (request == null) {
2180                            return;
2181                    }
2182    
2183                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
2184                            WebKeys.THEME_DISPLAY);
2185    
2186                    String layoutFullURL = PortalUtil.getLayoutFullURL(themeDisplay);
2187    
2188                    if (Validator.isNull(layoutFullURL)) {
2189                            return;
2190                    }
2191    
2192                    Map<String, String> parts = new HashMap<>();
2193    
2194                    String excerpt = StringUtil.shorten(
2195                            HtmlUtil.extractText(entry.getContent()),
2196                            PropsValues.BLOGS_LINKBACK_EXCERPT_LENGTH);
2197                    String url =
2198                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/" +
2199                                    entry.getUrlTitle();
2200    
2201                    parts.put("title", entry.getTitle());
2202                    parts.put("excerpt", excerpt);
2203                    parts.put("url", url);
2204                    parts.put("blog_name", entry.getUserName());
2205    
2206                    Set<String> trackbacksSet = null;
2207    
2208                    if (ArrayUtil.isNotEmpty(trackbacks)) {
2209                            trackbacksSet = SetUtil.fromArray(trackbacks);
2210                    }
2211                    else {
2212                            trackbacksSet = new HashSet<>();
2213                    }
2214    
2215                    if (pingOldTrackbacks) {
2216                            trackbacksSet.addAll(
2217                                    SetUtil.fromArray(StringUtil.split(entry.getTrackbacks())));
2218    
2219                            entry.setTrackbacks(StringPool.BLANK);
2220    
2221                            blogsEntryPersistence.update(entry);
2222                    }
2223    
2224                    Set<String> oldTrackbacks = SetUtil.fromArray(
2225                            StringUtil.split(entry.getTrackbacks()));
2226    
2227                    Set<String> validTrackbacks = new HashSet<>();
2228    
2229                    for (String trackback : trackbacksSet) {
2230                            if (oldTrackbacks.contains(trackback)) {
2231                                    continue;
2232                            }
2233    
2234                            try {
2235                                    if (LinkbackProducerUtil.sendTrackback(trackback, parts)) {
2236                                            validTrackbacks.add(trackback);
2237                                    }
2238                            }
2239                            catch (Exception e) {
2240                                    _log.error("Error while sending trackback at " + trackback, e);
2241                            }
2242                    }
2243    
2244                    if (!validTrackbacks.isEmpty()) {
2245                            String newTrackbacks = StringUtil.merge(validTrackbacks);
2246    
2247                            if (Validator.isNotNull(entry.getTrackbacks())) {
2248                                    newTrackbacks += StringPool.COMMA + entry.getTrackbacks();
2249                            }
2250    
2251                            entry.setTrackbacks(newTrackbacks);
2252    
2253                            blogsEntryPersistence.update(entry);
2254                    }
2255            }
2256    
2257            protected BlogsEntry startWorkflowInstance(
2258                            long userId, BlogsEntry entry, ServiceContext serviceContext)
2259                    throws PortalException {
2260    
2261                    Map<String, Serializable> workflowContext = new HashMap<>();
2262    
2263                    workflowContext.put(
2264                            WorkflowConstants.CONTEXT_URL, getEntryURL(entry, serviceContext));
2265    
2266                    String userPortraitURL = StringPool.BLANK;
2267                    String userURL = StringPool.BLANK;
2268    
2269                    if (serviceContext.getThemeDisplay() != null) {
2270                            User user = userPersistence.findByPrimaryKey(userId);
2271    
2272                            userPortraitURL = user.getPortraitURL(
2273                                    serviceContext.getThemeDisplay());
2274                            userURL = user.getDisplayURL(serviceContext.getThemeDisplay());
2275                    }
2276    
2277                    workflowContext.put(
2278                            WorkflowConstants.CONTEXT_USER_PORTRAIT_URL, userPortraitURL);
2279                    workflowContext.put(WorkflowConstants.CONTEXT_USER_URL, userURL);
2280    
2281                    return WorkflowHandlerRegistryUtil.startWorkflowInstance(
2282                            entry.getCompanyId(), entry.getGroupId(), userId,
2283                            BlogsEntry.class.getName(), entry.getEntryId(), entry,
2284                            serviceContext, workflowContext);
2285            }
2286    
2287            protected void validate(long smallImageFileEntryId) throws PortalException {
2288                    String[] imageExtensions = PrefsPropsUtil.getStringArray(
2289                            PropsKeys.BLOGS_IMAGE_EXTENSIONS, StringPool.COMMA);
2290    
2291                    if (smallImageFileEntryId != 0) {
2292                            FileEntry fileEntry = PortletFileRepositoryUtil.getPortletFileEntry(
2293                                    smallImageFileEntryId);
2294    
2295                            boolean validSmallImageExtension = false;
2296    
2297                            for (String _imageExtension : imageExtensions) {
2298                                    if (StringPool.STAR.equals(_imageExtension) ||
2299                                            _imageExtension.equals(
2300                                                    StringPool.PERIOD + fileEntry.getExtension())) {
2301    
2302                                            validSmallImageExtension = true;
2303    
2304                                            break;
2305                                    }
2306                            }
2307    
2308                            if (!validSmallImageExtension) {
2309                                    throw new EntrySmallImageNameException(
2310                                            "Invalid small image for file entry " +
2311                                                    smallImageFileEntryId);
2312                            }
2313                    }
2314            }
2315    
2316            protected void validate(String title, String content)
2317                    throws PortalException {
2318    
2319                    if (Validator.isNull(title)) {
2320                            throw new EntryTitleException("Title is null");
2321                    }
2322    
2323                    int titleMaxLength = ModelHintsUtil.getMaxLength(
2324                            BlogsEntry.class.getName(), "title");
2325    
2326                    if (title.length() > titleMaxLength) {
2327                            throw new EntryTitleException(
2328                                    "Title has more than " + titleMaxLength + " characters");
2329                    }
2330    
2331                    if (Validator.isNull(content)) {
2332                            throw new EntryContentException("Content is null");
2333                    }
2334    
2335                    int contentMaxLength = ModelHintsUtil.getMaxLength(
2336                            BlogsEntry.class.getName(), "content");
2337    
2338                    if (content.length() > contentMaxLength) {
2339                            throw new EntryContentException(
2340                                    "Content has more than " + contentMaxLength + " characters");
2341                    }
2342            }
2343    
2344            protected CommentManager commentManager =
2345                    CommentManagerUtil.getCommentManager();
2346    
2347            private static final String _COVER_IMAGE_FOLDER_NAME = "Cover Image";
2348    
2349            private static final String _SMALL_IMAGE_FOLDER_NAME = "Small Image";
2350    
2351            private static final Log _log = LogFactoryUtil.getLog(
2352                    BlogsEntryLocalServiceImpl.class);
2353    
2354    }