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