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