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