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