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