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