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                                    if (PropsValues.BLOGS_ENTRY_COMMENTS_ENABLED) {
1207                                            mbMessageLocalService.restoreDiscussionFromTrash(
1208                                                    BlogsEntry.class.getName(), entryId);
1209                                    }
1210    
1211                                    trashEntryLocalService.deleteEntry(
1212                                            BlogsEntry.class.getName(), entryId);
1213                            }
1214    
1215                            if (oldStatus != WorkflowConstants.STATUS_IN_TRASH) {
1216    
1217                                    // Subscriptions
1218    
1219                                    notifySubscribers(entry, serviceContext);
1220    
1221                                    // Ping
1222    
1223                                    String[] trackbacks = (String[])serviceContext.getAttribute(
1224                                            "trackbacks");
1225                                    Boolean pingOldTrackbacks = ParamUtil.getBoolean(
1226                                            serviceContext, "pingOldTrackbacks");
1227    
1228                                    pingGoogle(entry, serviceContext);
1229                                    pingPingback(entry, serviceContext);
1230                                    pingTrackbacks(
1231                                            entry, trackbacks, pingOldTrackbacks, serviceContext);
1232                            }
1233                    }
1234                    else {
1235    
1236                            // Asset
1237    
1238                            assetEntryLocalService.updateVisible(
1239                                    BlogsEntry.class.getName(), entryId, false);
1240    
1241                            // Social
1242    
1243                            if ((status == WorkflowConstants.STATUS_SCHEDULED) &&
1244                                    (oldStatus != WorkflowConstants.STATUS_IN_TRASH)) {
1245    
1246                                    if (serviceContext.isCommandUpdate()) {
1247                                            socialActivityLocalService.addActivity(
1248                                                    user.getUserId(), entry.getGroupId(),
1249                                                    BlogsEntry.class.getName(), entryId,
1250                                                    BlogsActivityKeys.UPDATE_ENTRY,
1251                                                    extraDataJSONObject.toString(), 0);
1252                                    }
1253                                    else {
1254                                            socialActivityLocalService.addUniqueActivity(
1255                                                    user.getUserId(), entry.getGroupId(),
1256                                                    BlogsEntry.class.getName(), entryId,
1257                                                    BlogsActivityKeys.ADD_ENTRY,
1258                                                    extraDataJSONObject.toString(), 0);
1259                                    }
1260                            }
1261    
1262                            // Trash
1263    
1264                            if (status == WorkflowConstants.STATUS_IN_TRASH) {
1265                                    if (PropsValues.BLOGS_ENTRY_COMMENTS_ENABLED) {
1266                                            mbMessageLocalService.moveDiscussionToTrash(
1267                                                    BlogsEntry.class.getName(), entryId);
1268                                    }
1269    
1270                                    trashEntryLocalService.addTrashEntry(
1271                                            userId, entry.getGroupId(), BlogsEntry.class.getName(),
1272                                            entry.getEntryId(), entry.getUuid(), null, oldStatus, null,
1273                                            null);
1274                            }
1275                            else if (oldStatus == WorkflowConstants.STATUS_IN_TRASH) {
1276                                    if (PropsValues.BLOGS_ENTRY_COMMENTS_ENABLED) {
1277                                            mbMessageLocalService.restoreDiscussionFromTrash(
1278                                                    BlogsEntry.class.getName(), entryId);
1279                                    }
1280    
1281                                    trashEntryLocalService.deleteEntry(
1282                                            BlogsEntry.class.getName(), entryId);
1283                            }
1284                    }
1285    
1286                    return entry;
1287            }
1288    
1289            protected String getUniqueUrlTitle(long entryId, long groupId, String title)
1290                    throws SystemException {
1291    
1292                    String urlTitle = BlogsUtil.getUrlTitle(entryId, title);
1293    
1294                    for (int i = 1;; i++) {
1295                            BlogsEntry entry = blogsEntryPersistence.fetchByG_UT(
1296                                    groupId, urlTitle);
1297    
1298                            if ((entry == null) || (entryId == entry.getEntryId())) {
1299                                    break;
1300                            }
1301                            else {
1302                                    String suffix = StringPool.DASH + i;
1303    
1304                                    String prefix = urlTitle;
1305    
1306                                    if (urlTitle.length() > suffix.length()) {
1307                                            prefix = urlTitle.substring(
1308                                                    0, urlTitle.length() - suffix.length());
1309                                    }
1310    
1311                                    urlTitle = prefix + suffix;
1312                            }
1313                    }
1314    
1315                    return urlTitle;
1316            }
1317    
1318            protected String getUniqueUrlTitle(
1319                            long entryId, String title, String oldUrlTitle,
1320                            ServiceContext serviceContext)
1321                    throws SystemException {
1322    
1323                    String serviceContextUrlTitle = ParamUtil.getString(
1324                            serviceContext, "urlTitle");
1325    
1326                    String urlTitle = null;
1327    
1328                    if (Validator.isNotNull(serviceContextUrlTitle)) {
1329                            urlTitle = BlogsUtil.getUrlTitle(entryId, serviceContextUrlTitle);
1330                    }
1331                    else if (Validator.isNotNull(oldUrlTitle)) {
1332                            return oldUrlTitle;
1333                    }
1334                    else {
1335                            urlTitle = getUniqueUrlTitle(
1336                                    entryId, serviceContext.getScopeGroupId(), title);
1337                    }
1338    
1339                    BlogsEntry urlTitleEntry = blogsEntryPersistence.fetchByG_UT(
1340                            serviceContext.getScopeGroupId(), urlTitle);
1341    
1342                    if ((urlTitleEntry != null) &&
1343                            (urlTitleEntry.getEntryId() != entryId)) {
1344    
1345                            urlTitle = getUniqueUrlTitle(
1346                                    entryId, serviceContext.getScopeGroupId(), urlTitle);
1347                    }
1348    
1349                    return urlTitle;
1350            }
1351    
1352            protected void notifySubscribers(
1353                            BlogsEntry entry, ServiceContext serviceContext)
1354                    throws SystemException {
1355    
1356                    if (!entry.isApproved()) {
1357                            return;
1358                    }
1359    
1360                    String layoutFullURL = serviceContext.getLayoutFullURL();
1361    
1362                    if (Validator.isNull(layoutFullURL)) {
1363                            return;
1364                    }
1365    
1366                    PortletPreferences preferences =
1367                            ServiceContextUtil.getPortletPreferences(serviceContext);
1368    
1369                    if (preferences == null) {
1370                            long ownerId = entry.getGroupId();
1371                            int ownerType = PortletKeys.PREFS_OWNER_TYPE_GROUP;
1372                            long plid = PortletKeys.PREFS_PLID_SHARED;
1373                            String portletId = PortletKeys.BLOGS;
1374                            String defaultPreferences = null;
1375    
1376                            preferences = portletPreferencesLocalService.getPreferences(
1377                                    entry.getCompanyId(), ownerId, ownerType, plid, portletId,
1378                                    defaultPreferences);
1379                    }
1380    
1381                    if (serviceContext.isCommandAdd() &&
1382                            BlogsUtil.getEmailEntryAddedEnabled(preferences)) {
1383                    }
1384                    else if (serviceContext.isCommandUpdate() &&
1385                                     BlogsUtil.getEmailEntryUpdatedEnabled(preferences)) {
1386                    }
1387                    else {
1388                            return;
1389                    }
1390    
1391                    String entryURL =
1392                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs" +
1393                                    StringPool.SLASH + entry.getEntryId();
1394    
1395                    String fromName = BlogsUtil.getEmailFromName(
1396                            preferences, entry.getCompanyId());
1397                    String fromAddress = BlogsUtil.getEmailFromAddress(
1398                            preferences, entry.getCompanyId());
1399    
1400                    Map<Locale, String> localizedSubjectMap = null;
1401                    Map<Locale, String> localizedBodyMap = null;
1402    
1403                    if (serviceContext.isCommandUpdate()) {
1404                            localizedSubjectMap = BlogsUtil.getEmailEntryUpdatedSubjectMap(
1405                                    preferences);
1406                            localizedBodyMap = BlogsUtil.getEmailEntryUpdatedBodyMap(
1407                                    preferences);
1408                    }
1409                    else {
1410                            localizedSubjectMap = BlogsUtil.getEmailEntryAddedSubjectMap(
1411                                    preferences);
1412                            localizedBodyMap = BlogsUtil.getEmailEntryAddedBodyMap(preferences);
1413                    }
1414    
1415                    SubscriptionSender subscriptionSender = new SubscriptionSender();
1416    
1417                    subscriptionSender.setCompanyId(entry.getCompanyId());
1418                    subscriptionSender.setContextAttributes(
1419                            "[$BLOGS_ENTRY_STATUS_BY_USER_NAME$]", entry.getStatusByUserName(),
1420                            "[$BLOGS_ENTRY_URL$]", entryURL);
1421                    subscriptionSender.setContextUserPrefix("BLOGS_ENTRY");
1422                    subscriptionSender.setFrom(fromAddress, fromName);
1423                    subscriptionSender.setHtmlFormat(true);
1424                    subscriptionSender.setLocalizedBodyMap(localizedBodyMap);
1425                    subscriptionSender.setLocalizedSubjectMap(localizedSubjectMap);
1426                    subscriptionSender.setMailId("blogs_entry", entry.getEntryId());
1427                    subscriptionSender.setPortletId(PortletKeys.BLOGS);
1428                    subscriptionSender.setReplyToAddress(fromAddress);
1429                    subscriptionSender.setScopeGroupId(entry.getGroupId());
1430                    subscriptionSender.setServiceContext(serviceContext);
1431                    subscriptionSender.setUserId(entry.getUserId());
1432    
1433                    subscriptionSender.addPersistedSubscribers(
1434                            BlogsEntry.class.getName(), entry.getGroupId());
1435    
1436                    subscriptionSender.addPersistedSubscribers(
1437                            BlogsEntry.class.getName(), entry.getEntryId());
1438    
1439                    subscriptionSender.flushNotificationsAsync();
1440            }
1441    
1442            protected void pingGoogle(BlogsEntry entry, ServiceContext serviceContext)
1443                    throws PortalException, SystemException {
1444    
1445                    if (!PropsValues.BLOGS_PING_GOOGLE_ENABLED || !entry.isApproved()) {
1446                            return;
1447                    }
1448    
1449                    String layoutFullURL = PortalUtil.getLayoutFullURL(
1450                            serviceContext.getScopeGroupId(), PortletKeys.BLOGS);
1451    
1452                    if (Validator.isNull(layoutFullURL)) {
1453                            return;
1454                    }
1455    
1456                    if (layoutFullURL.contains("://localhost")) {
1457                            if (_log.isDebugEnabled()) {
1458                                    _log.debug(
1459                                            "Not pinging Google because of localhost URL " +
1460                                                    layoutFullURL);
1461                            }
1462    
1463                            return;
1464                    }
1465    
1466                    Group group = groupPersistence.findByPrimaryKey(entry.getGroupId());
1467    
1468                    StringBundler sb = new StringBundler(6);
1469    
1470                    String name = group.getDescriptiveName();
1471                    String url = layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs";
1472                    String changesURL =
1473                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/rss";
1474    
1475                    sb.append("http://blogsearch.google.com/ping?name=");
1476                    sb.append(HttpUtil.encodeURL(name));
1477                    sb.append("&url=");
1478                    sb.append(HttpUtil.encodeURL(url));
1479                    sb.append("&changesURL=");
1480                    sb.append(HttpUtil.encodeURL(changesURL));
1481    
1482                    String location = sb.toString();
1483    
1484                    if (_log.isInfoEnabled()) {
1485                            _log.info("Pinging Google at " + location);
1486                    }
1487    
1488                    try {
1489                            String response = HttpUtil.URLtoString(sb.toString());
1490    
1491                            if (_log.isInfoEnabled()) {
1492                                    _log.info("Google ping response: " + response);
1493                            }
1494                    }
1495                    catch (IOException ioe) {
1496                            _log.error("Unable to ping Google at " + location, ioe);
1497                    }
1498            }
1499    
1500            protected void pingPingback(BlogsEntry entry, ServiceContext serviceContext)
1501                    throws PortalException, SystemException {
1502    
1503                    if (!PropsValues.BLOGS_PINGBACK_ENABLED ||
1504                            !entry.isAllowPingbacks() || !entry.isApproved()) {
1505    
1506                            return;
1507                    }
1508    
1509                    HttpServletRequest request = serviceContext.getRequest();
1510    
1511                    if (request == null) {
1512                            return;
1513                    }
1514    
1515                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
1516                            WebKeys.THEME_DISPLAY);
1517    
1518                    String layoutFullURL = PortalUtil.getLayoutFullURL(themeDisplay);
1519    
1520                    if (Validator.isNull(layoutFullURL)) {
1521                            return;
1522                    }
1523    
1524                    String sourceUri =
1525                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/" +
1526                                    entry.getUrlTitle();
1527    
1528                    Source source = new Source(entry.getContent());
1529    
1530                    List<StartTag> tags = source.getAllStartTags("a");
1531    
1532                    for (StartTag tag : tags) {
1533                            String targetUri = tag.getAttributeValue("href");
1534    
1535                            if (Validator.isNotNull(targetUri)) {
1536                                    try {
1537                                            LinkbackProducerUtil.sendPingback(sourceUri, targetUri);
1538                                    }
1539                                    catch (Exception e) {
1540                                            _log.error("Error while sending pingback " + targetUri, e);
1541                                    }
1542                            }
1543                    }
1544            }
1545    
1546            protected void pingTrackbacks(
1547                            BlogsEntry entry, String[] trackbacks, boolean pingOldTrackbacks,
1548                            ServiceContext serviceContext)
1549                    throws PortalException, SystemException {
1550    
1551                    if (!PropsValues.BLOGS_TRACKBACK_ENABLED ||
1552                            !entry.isAllowTrackbacks() || !entry.isApproved()) {
1553    
1554                            return;
1555                    }
1556    
1557                    HttpServletRequest request = serviceContext.getRequest();
1558    
1559                    if (request == null) {
1560                            return;
1561                    }
1562    
1563                    ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
1564                            WebKeys.THEME_DISPLAY);
1565    
1566                    String layoutFullURL = PortalUtil.getLayoutFullURL(themeDisplay);
1567    
1568                    if (Validator.isNull(layoutFullURL)) {
1569                            return;
1570                    }
1571    
1572                    Map<String, String> parts = new HashMap<String, String>();
1573    
1574                    String excerpt = StringUtil.shorten(
1575                            HtmlUtil.extractText(entry.getContent()),
1576                            PropsValues.BLOGS_LINKBACK_EXCERPT_LENGTH);
1577                    String url =
1578                            layoutFullURL + Portal.FRIENDLY_URL_SEPARATOR + "blogs/" +
1579                                    entry.getUrlTitle();
1580    
1581                    parts.put("title", entry.getTitle());
1582                    parts.put("excerpt", excerpt);
1583                    parts.put("url", url);
1584                    parts.put("blog_name", entry.getUserName());
1585    
1586                    Set<String> trackbacksSet = null;
1587    
1588                    if (ArrayUtil.isNotEmpty(trackbacks)) {
1589                            trackbacksSet = SetUtil.fromArray(trackbacks);
1590                    }
1591                    else {
1592                            trackbacksSet = new HashSet<String>();
1593                    }
1594    
1595                    if (pingOldTrackbacks) {
1596                            trackbacksSet.addAll(
1597                                    SetUtil.fromArray(StringUtil.split(entry.getTrackbacks())));
1598    
1599                            entry.setTrackbacks(StringPool.BLANK);
1600    
1601                            blogsEntryPersistence.update(entry);
1602                    }
1603    
1604                    Set<String> oldTrackbacks = SetUtil.fromArray(
1605                            StringUtil.split(entry.getTrackbacks()));
1606    
1607                    Set<String> validTrackbacks = new HashSet<String>();
1608    
1609                    for (String trackback : trackbacksSet) {
1610                            if (oldTrackbacks.contains(trackback)) {
1611                                    continue;
1612                            }
1613    
1614                            try {
1615                                    if (LinkbackProducerUtil.sendTrackback(trackback, parts)) {
1616                                            validTrackbacks.add(trackback);
1617                                    }
1618                            }
1619                            catch (Exception e) {
1620                                    _log.error("Error while sending trackback at " + trackback, e);
1621                            }
1622                    }
1623    
1624                    if (!validTrackbacks.isEmpty()) {
1625                            String newTrackbacks = StringUtil.merge(validTrackbacks);
1626    
1627                            if (Validator.isNotNull(entry.getTrackbacks())) {
1628                                    newTrackbacks += StringPool.COMMA + entry.getTrackbacks();
1629                            }
1630    
1631                            entry.setTrackbacks(newTrackbacks);
1632    
1633                            blogsEntryPersistence.update(entry);
1634                    }
1635            }
1636    
1637            protected void saveImages(
1638                            boolean smallImage, long smallImageId, byte[] smallImageBytes)
1639                    throws PortalException, SystemException {
1640    
1641                    if (smallImage) {
1642                            if (smallImageBytes != null) {
1643                                    imageLocalService.updateImage(smallImageId, smallImageBytes);
1644                            }
1645                    }
1646                    else {
1647                            imageLocalService.deleteImage(smallImageId);
1648                    }
1649            }
1650    
1651            protected void validate(
1652                            String title, String content, boolean smallImage,
1653                            String smallImageURL, String smallImageFileName,
1654                            byte[] smallImageBytes)
1655                    throws PortalException, SystemException {
1656    
1657                    if (Validator.isNull(title)) {
1658                            throw new EntryTitleException();
1659                    }
1660                    else if (Validator.isNull(content)) {
1661                            throw new EntryContentException();
1662                    }
1663    
1664                    String[] imageExtensions = PrefsPropsUtil.getStringArray(
1665                            PropsKeys.BLOGS_IMAGE_EXTENSIONS, StringPool.COMMA);
1666    
1667                    if (smallImage && Validator.isNull(smallImageURL) &&
1668                            (smallImageBytes != null)) {
1669    
1670                            if (smallImageFileName != null) {
1671                                    boolean validSmallImageExtension = false;
1672    
1673                                    for (String _imageExtension : imageExtensions) {
1674                                            if (StringPool.STAR.equals(_imageExtension) ||
1675                                                    StringUtil.endsWith(
1676                                                            smallImageFileName, _imageExtension)) {
1677    
1678                                                    validSmallImageExtension = true;
1679    
1680                                                    break;
1681                                            }
1682                                    }
1683    
1684                                    if (!validSmallImageExtension) {
1685                                            throw new EntrySmallImageNameException(smallImageFileName);
1686                                    }
1687                            }
1688    
1689                            long smallImageMaxSize = PrefsPropsUtil.getLong(
1690                                    PropsKeys.BLOGS_IMAGE_SMALL_MAX_SIZE);
1691    
1692                            if ((smallImageMaxSize > 0) &&
1693                                    (smallImageBytes.length > smallImageMaxSize)) {
1694    
1695                                    throw new EntrySmallImageSizeException();
1696                            }
1697                    }
1698            }
1699    
1700            private static Log _log = LogFactoryUtil.getLog(
1701                    BlogsEntryLocalServiceImpl.class);
1702    
1703    }