/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.so.activities.hook.social; import com.liferay.asset.kernel.AssetRendererFactoryRegistryUtil; import com.liferay.asset.kernel.model.AssetEntry; import com.liferay.asset.kernel.model.AssetRenderer; import com.liferay.asset.kernel.model.AssetRendererFactory; import com.liferay.message.boards.kernel.model.MBMessage; import com.liferay.message.boards.kernel.service.MBMessageLocalServiceUtil; import com.liferay.portal.kernel.dao.orm.DynamicQuery; import com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil; import com.liferay.portal.kernel.dao.orm.ProjectionFactoryUtil; import com.liferay.portal.kernel.dao.orm.QueryUtil; import com.liferay.portal.kernel.dao.orm.RestrictionsFactoryUtil; import com.liferay.portal.kernel.model.Group; import com.liferay.portal.kernel.parsers.bbcode.BBCodeTranslatorUtil; import com.liferay.portal.kernel.portlet.LiferayPortletRequest; import com.liferay.portal.kernel.security.permission.ActionKeys; import com.liferay.portal.kernel.security.permission.PermissionChecker; import com.liferay.portal.kernel.service.GroupLocalServiceUtil; import com.liferay.portal.kernel.service.ServiceContext; import com.liferay.portal.kernel.theme.ThemeDisplay; import com.liferay.portal.kernel.util.ClassResourceBundleLoader; import com.liferay.portal.kernel.util.FastDateFormatFactoryUtil; import com.liferay.portal.kernel.util.HtmlUtil; import com.liferay.portal.kernel.util.ResourceBundleLoader; import com.liferay.portal.kernel.util.StringBundler; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.kernel.util.Time; import com.liferay.portal.kernel.util.Validator; import com.liferay.so.activities.util.PortletPropsValues; import com.liferay.social.kernel.model.BaseSocialActivityInterpreter; import com.liferay.social.kernel.model.SocialActivity; import com.liferay.social.kernel.model.SocialActivityFeedEntry; import com.liferay.social.kernel.model.SocialActivitySet; import com.liferay.social.kernel.service.SocialActivityLocalServiceUtil; import com.liferay.social.kernel.service.SocialActivitySetLocalServiceUtil; import com.liferay.trash.kernel.util.TrashUtil; import com.liferay.wiki.model.WikiPageResource; import java.text.DateFormat; import java.text.Format; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * @author Brian Wing Shun Chan * @author Ryan Park * @author Matthew Kong */ public abstract class SOSocialActivityInterpreter extends BaseSocialActivityInterpreter { @Override public String getSelector() { return _SELECTOR; } @Override protected SocialActivityFeedEntry doInterpret( SocialActivity activity, ServiceContext serviceContext) throws Exception { return super.doInterpret(activity, serviceContext); } @Override protected SocialActivityFeedEntry doInterpret( SocialActivitySet activitySet, ServiceContext serviceContext) throws Exception { List<SocialActivity> viewableActivities = getViewableActivities( activitySet, serviceContext); if (viewableActivities.isEmpty()) { return null; } if (viewableActivities.size() == 1) { SocialActivity activity = viewableActivities.get(0); return doInterpret(activity, serviceContext); } String link = getLink(activitySet, serviceContext); String title = getTitle(activitySet, serviceContext); if (Validator.isNull(title)) { return null; } String body = getBody(activitySet, serviceContext); return new SocialActivityFeedEntry(link, title, body); } protected List<Long> getActivitySetUserIds(long activitySetId) { DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass( SocialActivity.class); dynamicQuery.add( RestrictionsFactoryUtil.eq("activitySetId", activitySetId)); dynamicQuery.setProjection( ProjectionFactoryUtil.distinct( ProjectionFactoryUtil.property("userId"))); return SocialActivityLocalServiceUtil.dynamicQuery(dynamicQuery); } protected AssetRenderer getAssetRenderer(String className, long classPK) throws Exception { AssetRendererFactory assetRendererFactory = AssetRendererFactoryRegistryUtil.getAssetRendererFactoryByClassName( className); return assetRendererFactory.getAssetRenderer(classPK); } protected String getAttachmentTitle( SocialActivity activity, WikiPageResource pageResource, ServiceContext serviceContext) throws Exception { return null; } protected String getBody( SocialActivitySet activitySet, ServiceContext serviceContext) throws Exception { StringBundler sb = new StringBundler(); sb.append("<div class=\"grouped-activity-body-container\">"); sb.append("<div class=\"grouped-activity-body\">"); List<SocialActivity> activities = getViewableActivities( activitySet, serviceContext); for (SocialActivity activity : activities) { SocialActivityFeedEntry subfeedEntry = getSubfeedEntry( activity, serviceContext); if (subfeedEntry == null) { continue; } sb.append("<div class=\"activity-subentry\">"); sb.append("<span class=\"activity-subentry-title\">"); sb.append(subfeedEntry.getTitle()); sb.append("</span><span class=\"activity-subentry-body\">"); sb.append(subfeedEntry.getBody()); sb.append("</span><span class=\"activity-subentry-link\">"); sb.append(subfeedEntry.getLink()); sb.append("</span></div>"); } sb.append("</div></div>"); return sb.toString(); } protected long getDisplayDate(SocialActivity activity) throws Exception { long activitySetId = activity.getActivitySetId(); if (activitySetId > 0) { SocialActivitySet socialActivitySet = SocialActivitySetLocalServiceUtil.fetchSocialActivitySet( activitySetId); if ((socialActivitySet != null) && (socialActivitySet.getActivityCount() == 1) && (socialActivitySet.getModifiedDate() > socialActivitySet.getCreateDate())) { return socialActivitySet.getModifiedDate(); } } return activity.getCreateDate(); } protected String getLink( SocialActivitySet activitySet, ServiceContext serviceContext) throws Exception { return null; } protected String getLinkURL( String className, long classPK, ServiceContext serviceContext) throws Exception { AssetRenderer assetRenderer = getAssetRenderer(className, classPK); String url = assetRenderer.getURLViewInContext( serviceContext.getLiferayPortletRequest(), serviceContext.getLiferayPortletResponse(), null); return addNoSuchEntryRedirect(url, className, classPK, serviceContext); } protected String getPageTitle( String className, long classPK, ServiceContext serviceContext) throws Exception { String linkURL = getLinkURL(className, classPK, serviceContext); AssetRenderer assetRenderer = getAssetRenderer(className, classPK); LiferayPortletRequest liferayPortletRequest = serviceContext.getLiferayPortletRequest(); if (Validator.isNotNull( assetRenderer.getIconPath(liferayPortletRequest))) { return wrapLink( linkURL, assetRenderer.getIconPath(liferayPortletRequest), HtmlUtil.escape( assetRenderer.getTitle(serviceContext.getLocale()))); } return wrapLink( linkURL, HtmlUtil.escape( assetRenderer.getTitle(serviceContext.getLocale()))); } @Override protected ResourceBundleLoader getResourceBundleLoader() { return _resourceBundleLoader; } protected SocialActivityFeedEntry getSubfeedEntry( SocialActivity activity, ServiceContext serviceContext) throws Exception { String link = getLink(activity, serviceContext); String className = activity.getClassName(); String title = getPageTitle( className, activity.getClassPK(), serviceContext); AssetRenderer assetRenderer = getAssetRenderer( className, activity.getClassPK()); String body = assetRenderer.getSummary(); if (className.equals(MBMessage.class.getName())) { MBMessage mbMessage = MBMessageLocalServiceUtil.getMBMessage( activity.getClassPK()); if (mbMessage.isFormatBBCode()) { body = HtmlUtil.extractText( BBCodeTranslatorUtil.getHTML(mbMessage.getBody())); } } body = StringUtil.shorten(HtmlUtil.escape(body), 200); return new SocialActivityFeedEntry(link, title, body); } protected String getTitle( long activitySetId, long groupId, long userId, long displayDate, ServiceContext serviceContext) throws Exception { StringBundler sb = new StringBundler(8); sb.append("<div class=\"activity-header\">"); sb.append("<div class=\"activity-user-name\">"); String userName = getUserName(userId, serviceContext); int otherUsersCount = 0; if (activitySetId > 0) { List<Long> userIds = getActivitySetUserIds(activitySetId); otherUsersCount = userIds.size() - 1; } if ((groupId != serviceContext.getScopeGroupId()) && (groupId > 0)) { String groupName = getGroupName(groupId, serviceContext); if (otherUsersCount > 0) { sb.append( serviceContext.translate( "x-and-x-others-in-x", new Object[] {userName, otherUsersCount, groupName})); } else { sb.append( serviceContext.translate( "x-in-x", new Object[] {userName, groupName})); } } else if (otherUsersCount > 0) { sb.append( serviceContext.translate( "x-and-x-others", new Object[] {userName, otherUsersCount})); } else { sb.append(userName); } sb.append("</div><div class=\"activity-time\" title=\""); Format dateFormatDate = FastDateFormatFactoryUtil.getDateTime( DateFormat.FULL, DateFormat.SHORT, serviceContext.getLocale(), serviceContext.getTimeZone()); Date activityDate = new Date(displayDate); sb.append(dateFormatDate.format(activityDate)); sb.append("\">"); Format dateFormat = FastDateFormatFactoryUtil.getDate( DateFormat.FULL, serviceContext.getLocale(), serviceContext.getTimeZone()); String relativeTimeDescription = Time.getRelativeTimeDescription( displayDate, serviceContext.getLocale(), serviceContext.getTimeZone(), dateFormat); sb.append(relativeTimeDescription); sb.append("</div></div>"); return sb.toString(); } @Override protected String getTitle( SocialActivity activity, ServiceContext serviceContext) throws Exception { StringBundler sb = new StringBundler(4); sb.append( getTitle( 0, activity.getGroupId(), activity.getUserId(), getDisplayDate(activity), serviceContext)); sb.append("<div class=\"activity-action\">"); String titlePattern = getTitlePattern(null, activity); if (Validator.isNull(titlePattern)) { return null; } Object[] titleArguments = getTitleArguments( null, activity, null, null, serviceContext); sb.append(serviceContext.translate(titlePattern, titleArguments)); sb.append("</div>"); return sb.toString(); } protected String getTitle( SocialActivitySet activitySet, ServiceContext serviceContext) throws Exception { StringBundler sb = new StringBundler(4); sb.append( getTitle( activitySet.getActivitySetId(), activitySet.getGroupId(), activitySet.getUserId(), activitySet.getModifiedDate(), serviceContext)); sb.append("<div class=\"activity-action\">"); String titlePattern = getTitlePattern(null, activitySet); if (Validator.isNull(titlePattern)) { return null; } Object[] titleArguments = getTitleArguments( null, activitySet, null, null, serviceContext); sb.append(serviceContext.translate(titlePattern, titleArguments)); sb.append("</div>"); return sb.toString(); } @Override protected Object[] getTitleArguments( String groupName, SocialActivity socialActivity, String link, String title, ServiceContext serviceContext) throws Exception { return null; } protected Object[] getTitleArguments( String groupName, SocialActivitySet activitySet, String link, String title, ServiceContext serviceContext) throws Exception { List<SocialActivity> viewableActivities = getViewableActivities( activitySet, serviceContext); return new Object[] {viewableActivities.size()}; } protected String getTitlePattern( String groupName, SocialActivitySet activitySet) throws Exception { return StringPool.BLANK; } protected List<SocialActivity> getViewableActivities( SocialActivitySet activitySet, ServiceContext serviceContext) throws Exception { List<SocialActivity> viewableActivities = new ArrayList<>(); List<SocialActivity> activities = SocialActivityLocalServiceUtil.getActivitySetActivities( activitySet.getActivitySetId(), QueryUtil.ALL_POS, QueryUtil.ALL_POS); for (SocialActivity activity : activities) { if (!hasPermissions(activity, serviceContext)) { continue; } Group group = GroupLocalServiceUtil.fetchGroup( activity.getGroupId()); if ((group != null) && group.isUser()) { continue; } if (TrashUtil.isInTrash( activity.getClassName(), activity.getClassPK())) { continue; } if (!isVisible(activity)) { continue; } viewableActivities.add(activity); } return viewableActivities; } @Override protected boolean hasPermissions( PermissionChecker permissionChecker, SocialActivity activity, String actionId, ServiceContext serviceContext) throws Exception { AssetEntry assetEntry = activity.getAssetEntry(); AssetRenderer assetRenderer = assetEntry.getAssetRenderer(); return assetRenderer.hasViewPermission(permissionChecker); } protected boolean hasPermissions( SocialActivity activity, ServiceContext serviceContext) throws Exception { ThemeDisplay themeDisplay = serviceContext.getThemeDisplay(); PermissionChecker permissionChecker = themeDisplay.getPermissionChecker(); return hasPermissions( permissionChecker, activity, ActionKeys.VIEW, serviceContext); } protected boolean hasPermissions( SocialActivitySet activitySet, ServiceContext serviceContext) throws Exception { ThemeDisplay themeDisplay = serviceContext.getThemeDisplay(); PermissionChecker permissionChecker = themeDisplay.getPermissionChecker(); List<SocialActivity> activities = SocialActivityLocalServiceUtil.getActivitySetActivities( activitySet.getActivitySetId(), 0, 1); if (!activities.isEmpty()) { SocialActivity activity = activities.get(0); return hasPermissions( permissionChecker, activity, ActionKeys.VIEW, serviceContext); } return false; } protected boolean isExpired( SocialActivitySet activitySet, boolean comment) { long age = System.currentTimeMillis() - activitySet.getCreateDate(); long timeWindow = Time.MINUTE * PortletPropsValues.SOCIAL_ACTIVITY_SETS_BUNDLING_TIME_WINDOW; if (comment) { timeWindow = Time.MINUTE * PortletPropsValues. SOCIAL_ACTIVITY_SETS_COMMENTS_BUNDLING_TIME_WINDOW; } if (age > timeWindow) { return true; } return false; } protected boolean isVisible(SocialActivity activity) throws Exception { return true; } protected String wrapLink(String link, String iconPath, String text) { StringBundler sb = new StringBundler(5); sb.append("<a href=\""); sb.append(link); sb.append("\">"); sb.append("<span><img class=\"icon\" src=\""); sb.append(iconPath); sb.append("\"></span><span>"); sb.append(text); sb.append("</span>"); sb.append("</a>"); return sb.toString(); } private static final String _SELECTOR = "SO"; private final ResourceBundleLoader _resourceBundleLoader = new ClassResourceBundleLoader( "content.Language", SOSocialActivityInterpreter.class); }