/**
* 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.asset.publisher.web.internal.messaging;
import aQute.bnd.annotation.ProviderType;
import com.liferay.asset.kernel.AssetRendererFactoryRegistryUtil;
import com.liferay.asset.kernel.model.AssetEntry;
import com.liferay.asset.kernel.service.persistence.AssetEntryQuery;
import com.liferay.asset.publisher.web.constants.AssetPublisherPortletKeys;
import com.liferay.asset.publisher.web.internal.configuration.AssetPublisherWebConfiguration;
import com.liferay.asset.publisher.web.util.AssetPublisherUtil;
import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery;
import com.liferay.portal.kernel.dao.orm.DynamicQuery;
import com.liferay.portal.kernel.dao.orm.Property;
import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.model.Layout;
import com.liferay.portal.kernel.model.PortletInstance;
import com.liferay.portal.kernel.model.User;
import com.liferay.portal.kernel.module.configuration.ConfigurationProvider;
import com.liferay.portal.kernel.portlet.PortletPreferencesFactoryUtil;
import com.liferay.portal.kernel.search.BaseModelSearchResult;
import com.liferay.portal.kernel.search.SearchContext;
import com.liferay.portal.kernel.search.SearchContextFactory;
import com.liferay.portal.kernel.security.permission.ActionKeys;
import com.liferay.portal.kernel.security.permission.PermissionChecker;
import com.liferay.portal.kernel.security.permission.PermissionCheckerFactoryUtil;
import com.liferay.portal.kernel.service.LayoutLocalService;
import com.liferay.portal.kernel.service.PortletPreferencesLocalService;
import com.liferay.portal.kernel.service.UserLocalService;
import com.liferay.portal.kernel.util.Accessor;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.LocaleThreadLocal;
import com.liferay.portal.kernel.util.LocaleUtil;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.SubscriptionSender;
import com.liferay.portal.kernel.util.TimeZoneThreadLocal;
import com.liferay.portlet.asset.service.permission.AssetEntryPermission;
import com.liferay.portlet.asset.util.AssetUtil;
import com.liferay.portlet.configuration.kernel.util.PortletConfigurationUtil;
import com.liferay.subscription.model.Subscription;
import com.liferay.subscription.service.SubscriptionLocalService;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.portlet.PortletException;
import javax.portlet.PortletPreferences;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* @author Eudaldo Alonso
*/
@Component(immediate = true, service = AssetEntriesCheckerUtil.class)
@ProviderType
public class AssetEntriesCheckerUtil {
public void checkAssetEntries() throws Exception {
ActionableDynamicQuery actionableDynamicQuery =
_portletPreferencesLocalService.getActionableDynamicQuery();
actionableDynamicQuery.setAddCriteriaMethod(
new ActionableDynamicQuery.AddCriteriaMethod() {
@Override
public void addCriteria(DynamicQuery dynamicQuery) {
Property property = PropertyFactoryUtil.forName(
"portletId");
PortletInstance portletInstance = new PortletInstance(
AssetPublisherPortletKeys.ASSET_PUBLISHER,
StringPool.PERCENT);
dynamicQuery.add(
property.like(portletInstance.getPortletInstanceKey()));
}
});
actionableDynamicQuery.setPerformActionMethod(
new ActionableDynamicQuery.PerformActionMethod
<com.liferay.portal.kernel.model.PortletPreferences>() {
@Override
public void performAction(
com.liferay.portal.kernel.model.PortletPreferences
portletPreferences)
throws PortalException {
_checkAssetEntries(portletPreferences);
}
});
actionableDynamicQuery.performActions();
}
@Reference(unbind = "-")
protected void setAssetPublisherUtil(
AssetPublisherUtil assetPublisherUtil) {
_assetPublisherUtil = assetPublisherUtil;
}
@Reference(unbind = "-")
protected void setLayoutLocalService(
LayoutLocalService layoutLocalService) {
_layoutLocalService = layoutLocalService;
}
@Reference(unbind = "-")
protected void setPortletPreferencesLocalService(
PortletPreferencesLocalService portletPreferencesLocalService) {
_portletPreferencesLocalService = portletPreferencesLocalService;
}
@Reference(unbind = "-")
protected void setSubscriptionLocalService(
SubscriptionLocalService subscriptionLocalService) {
_subscriptionLocalService = subscriptionLocalService;
}
@Reference(unbind = "-")
protected void setUserLocalService(UserLocalService userLocalService) {
_userLocalService = userLocalService;
}
private static List<AssetEntry> _filterAssetEntries(
long userId, List<AssetEntry> assetEntries) {
User user = _userLocalService.fetchUser(userId);
if (user == null) {
return Collections.emptyList();
}
PermissionChecker permissionChecker = null;
try {
permissionChecker = PermissionCheckerFactoryUtil.create(user);
}
catch (Exception e) {
return Collections.emptyList();
}
List<AssetEntry> filteredAssetEntries = new ArrayList<>();
for (AssetEntry assetEntry : assetEntries) {
try {
if (AssetEntryPermission.contains(
permissionChecker, assetEntry, ActionKeys.VIEW)) {
filteredAssetEntries.add(assetEntry);
}
}
catch (Exception e) {
continue;
}
}
return filteredAssetEntries;
}
private static SubscriptionSender _getSubscriptionSender(
PortletPreferences portletPreferences, List<AssetEntry> assetEntries) {
if (assetEntries.isEmpty()) {
return null;
}
AssetEntry assetEntry = assetEntries.get(0);
String fromName = _assetPublisherUtil.getEmailFromName(
portletPreferences, assetEntry.getCompanyId());
String fromAddress = _assetPublisherUtil.getEmailFromAddress(
portletPreferences, assetEntry.getCompanyId());
Map<Locale, String> localizedSubjectMap =
_assetPublisherUtil.getEmailAssetEntryAddedSubjectMap(
portletPreferences);
Map<Locale, String> localizedBodyMap =
_assetPublisherUtil.getEmailAssetEntryAddedBodyMap(
portletPreferences);
SubscriptionSender subscriptionSender = new SubscriptionSender();
subscriptionSender.setCompanyId(assetEntry.getCompanyId());
subscriptionSender.setContextAttributes(
"[$ASSET_ENTRIES$]",
ListUtil.toString(
assetEntries, _titleAccessor, StringPool.COMMA_AND_SPACE));
subscriptionSender.setFrom(fromAddress, fromName);
subscriptionSender.setHtmlFormat(true);
subscriptionSender.setLocalizedBodyMap(localizedBodyMap);
subscriptionSender.setLocalizedPortletTitleMap(
PortletConfigurationUtil.getPortletTitleMap(portletPreferences));
subscriptionSender.setLocalizedSubjectMap(localizedSubjectMap);
subscriptionSender.setMailId("asset_entry", assetEntry.getEntryId());
subscriptionSender.setPortletId(
AssetPublisherPortletKeys.ASSET_PUBLISHER);
subscriptionSender.setReplyToAddress(fromAddress);
return subscriptionSender;
}
private static void _notifySubscribers(
List<Subscription> subscriptions, PortletPreferences portletPreferences,
List<AssetEntry> assetEntries) {
if (!_assetPublisherUtil.getEmailAssetEntryAddedEnabled(
portletPreferences)) {
return;
}
Map<List<AssetEntry>, List<User>> assetEntriesToUsersMap =
new HashMap<>();
for (Subscription subscription : subscriptions) {
long userId = subscription.getUserId();
User user = _userLocalService.fetchUser(userId);
if ((user == null) || !user.isActive()) {
continue;
}
List<AssetEntry> filteredAssetEntries = _filterAssetEntries(
userId, assetEntries);
if (filteredAssetEntries.isEmpty()) {
continue;
}
List<User> users = assetEntriesToUsersMap.get(filteredAssetEntries);
if (users == null) {
users = new LinkedList<>();
assetEntriesToUsersMap.put(filteredAssetEntries, users);
}
users.add(user);
}
for (Map.Entry<List<AssetEntry>, List<User>> entry :
assetEntriesToUsersMap.entrySet()) {
List<AssetEntry> filteredAssetEntries = entry.getKey();
List<User> users = entry.getValue();
SubscriptionSender subscriptionSender = _getSubscriptionSender(
portletPreferences, filteredAssetEntries);
if (subscriptionSender == null) {
continue;
}
for (User user : users) {
subscriptionSender.addRuntimeSubscribers(
user.getEmailAddress(), user.getFullName());
}
subscriptionSender.setBulk(true);
subscriptionSender.flushNotificationsAsync();
}
}
private void _checkAssetEntries(
com.liferay.portal.kernel.model.PortletPreferences
portletPreferencesModel)
throws PortalException {
Layout layout = _layoutLocalService.fetchLayout(
portletPreferencesModel.getPlid());
if (layout == null) {
return;
}
PortletPreferences portletPreferences =
PortletPreferencesFactoryUtil.fromXML(
layout.getCompanyId(), portletPreferencesModel.getOwnerId(),
portletPreferencesModel.getOwnerType(),
portletPreferencesModel.getPlid(),
portletPreferencesModel.getPortletId(),
portletPreferencesModel.getPreferences());
if (!_assetPublisherUtil.getEmailAssetEntryAddedEnabled(
portletPreferences)) {
return;
}
List<AssetEntry> assetEntries = _getAssetEntries(
portletPreferences, layout);
if (assetEntries.isEmpty()) {
return;
}
long[] notifiedAssetEntryIds = GetterUtil.getLongValues(
portletPreferences.getValues("notifiedAssetEntryIds", null));
ArrayList<AssetEntry> newAssetEntries = new ArrayList<>();
for (AssetEntry assetEntry : assetEntries) {
if (!ArrayUtil.contains(
notifiedAssetEntryIds, assetEntry.getEntryId())) {
newAssetEntries.add(assetEntry);
}
}
List<Subscription> subscriptions =
_subscriptionLocalService.getSubscriptions(
portletPreferencesModel.getCompanyId(),
com.liferay.portal.kernel.model.PortletPreferences.class.
getName(),
_assetPublisherUtil.getSubscriptionClassPK(
portletPreferencesModel.getPlid(),
portletPreferencesModel.getPortletId()));
_notifySubscribers(subscriptions, portletPreferences, newAssetEntries);
try {
portletPreferences.setValues(
"notifiedAssetEntryIds",
StringUtil.split(
ListUtil.toString(
assetEntries, AssetEntry.ENTRY_ID_ACCESSOR)));
portletPreferences.store();
}
catch (IOException | PortletException e) {
throw new PortalException(e);
}
}
private List<AssetEntry> _getAssetEntries(
PortletPreferences portletPreferences, Layout layout)
throws PortalException {
AssetPublisherWebConfiguration assetPublisherWebConfiguration =
_configurationProvider.getCompanyConfiguration(
AssetPublisherWebConfiguration.class, layout.getCompanyId());
long[] groupIds = _assetPublisherUtil.getGroupIds(
portletPreferences, layout.getGroupId(), layout);
AssetEntryQuery assetEntryQuery =
_assetPublisherUtil.getAssetEntryQuery(
portletPreferences, groupIds, null, null);
assetEntryQuery.setGroupIds(groupIds);
boolean anyAssetType = GetterUtil.getBoolean(
portletPreferences.getValue("anyAssetType", null), true);
if (!anyAssetType) {
long[] availableClassNameIds =
AssetRendererFactoryRegistryUtil.getClassNameIds(
layout.getCompanyId());
long[] classNameIds = _assetPublisherUtil.getClassNameIds(
portletPreferences, availableClassNameIds);
assetEntryQuery.setClassNameIds(classNameIds);
}
long[] classTypeIds = GetterUtil.getLongValues(
portletPreferences.getValues("classTypeIds", null));
assetEntryQuery.setClassTypeIds(classTypeIds);
boolean enablePermissions = GetterUtil.getBoolean(
portletPreferences.getValue("enablePermissions", null));
assetEntryQuery.setEnablePermissions(enablePermissions);
assetEntryQuery.setEnd(
assetPublisherWebConfiguration.dynamicSubscriptionLimit());
boolean excludeZeroViewCount = GetterUtil.getBoolean(
portletPreferences.getValue("excludeZeroViewCount", null));
assetEntryQuery.setExcludeZeroViewCount(excludeZeroViewCount);
boolean showOnlyLayoutAssets = GetterUtil.getBoolean(
portletPreferences.getValue("showOnlyLayoutAssets", null));
if (showOnlyLayoutAssets) {
assetEntryQuery.setLayout(layout);
}
String orderByColumn1 = GetterUtil.getString(
portletPreferences.getValue("orderByColumn1", "modifiedDate"));
assetEntryQuery.setOrderByCol1(orderByColumn1);
String orderByColumn2 = GetterUtil.getString(
portletPreferences.getValue("orderByColumn2", "title"));
assetEntryQuery.setOrderByCol2(orderByColumn2);
String orderByType1 = GetterUtil.getString(
portletPreferences.getValue("orderByType1", "DESC"));
assetEntryQuery.setOrderByType1(orderByType1);
String orderByType2 = GetterUtil.getString(
portletPreferences.getValue("orderByType2", "ASC"));
assetEntryQuery.setOrderByType2(orderByType2);
assetEntryQuery.setStart(0);
try {
SearchContext searchContext = SearchContextFactory.getInstance(
new long[0], new String[0], null, layout.getCompanyId(),
StringPool.BLANK, layout,
LocaleThreadLocal.getSiteDefaultLocale(), layout.getGroupId(),
TimeZoneThreadLocal.getDefaultTimeZone(), 0);
BaseModelSearchResult<AssetEntry> baseModelSearchResult =
AssetUtil.searchAssetEntries(
searchContext, assetEntryQuery, 0,
assetPublisherWebConfiguration.dynamicSubscriptionLimit());
return baseModelSearchResult.getBaseModels();
}
catch (Exception e) {
return Collections.emptyList();
}
}
private static AssetPublisherUtil _assetPublisherUtil;
private static LayoutLocalService _layoutLocalService;
private static PortletPreferencesLocalService
_portletPreferencesLocalService;
private static SubscriptionLocalService _subscriptionLocalService;
private static final Accessor<AssetEntry, String> _titleAccessor =
new Accessor<AssetEntry, String>() {
@Override
public String get(AssetEntry assetEntry) {
return assetEntry.getTitle(LocaleUtil.getSiteDefault());
}
@Override
public Class<String> getAttributeClass() {
return String.class;
}
@Override
public Class<AssetEntry> getTypeClass() {
return AssetEntry.class;
}
};
private static UserLocalService _userLocalService;
@Reference
private ConfigurationProvider _configurationProvider;
}